GIT 8ba86486650c59f969c589c7d6c3dd4da734c75a git+ssh://master.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git commit 7478a94ba73721e78bee80215a71f106fe14f612 Author: Steve French Date: Thu May 18 18:25:59 2006 +0000 [CIFS] Fix typos in previous fix Signed-off-by: Steve French commit eedd2970e0efc0af3e3c038333a80e02e5eb5722 Author: Steve French Date: Wed May 17 23:15:14 2006 +0000 [CIFS] endian fix for new POSIX byte range lock support Signed-off-by: Alexey Dobriyan Signed-off-by: Steve French commit db20a979fd7c13bb11d6687d01034998b16d3156 Author: Steve French Date: Wed May 17 23:11:08 2006 +0000 [CIFS] fix memory leak in cifs session info struct on reconnect Signed-off-by: Steve French commit 9153bfb3d0f1d47ce13de0f074f13f90d3571ff1 Author: Steve French Date: Wed May 17 22:49:39 2006 +0000 [CIFS] ACPI suspend oops Wasn't able to reproduce a hard hang, but was able to get an oops if suspended the machine during a copy to the cifs mount. This led to some things hanging, including a "sync". Also got I/O errors when trying to access the mount afterwards (even when didn't see the oops), and had to unmount and remount in order to access the filesystem. This patch fixed the oops. Signed-off-by: Dave Kleikamp Signed-off-by: Steve French commit 2d84d92dc97a4b0548a7d27ab0344da031e6821b Author: Steve French Date: Tue May 2 21:41:23 2006 +0000 [CIFS] Do not limit the length of share names (was 100 for whole UNC name) during mount. Especially important for some non-Western languages. Signed-off-by: Steve French commit fcb63b946bfbbba5cf23364978b4ec6c4806bda6 Author: Steve French Date: Tue Apr 25 16:41:13 2006 +0000 FS] Fix new POSIX Locking for setting lock_type correctly on unlock Signed-off-by: Steve French --- diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 1a27ecb..7271bb0 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,3 +1,10 @@ +Version 1.43 +------------ +POSIX locking to servers which support CIFS POSIX Extensions +(disabled by default controlled by proc/fs/cifs/Experimental). +Handle conversion of long share names (especially Asian languages) +to Unicode during mount. + Version 1.42 ------------ Fix slow oplock break when mounted to different servers at the same time and diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 4e829dc..c98755d 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -99,5 +99,5 @@ extern ssize_t cifs_getxattr(struct dent extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern int cifs_ioctl (struct inode * inode, struct file * filep, unsigned int command, unsigned long arg); -#define CIFS_VERSION "1.42" +#define CIFS_VERSION "1.43" #endif /* _CIFSFS_H */ diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 2879ba3..310ea2f 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -267,7 +267,7 @@ extern int CIFSSMBLock(const int xid, st const int waitFlag); extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, const __u16 smb_file_id, const int get_flag, - const __u64 len, const __u64 offset, + const __u64 len, struct file_lock *, const __u16 lock_type, const int waitFlag); extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon); extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index fd36892..925881e 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1355,7 +1355,8 @@ CIFSSMBLock(const int xid, struct cifsTc int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, const __u16 smb_file_id, const int get_flag, const __u64 len, - const __u64 lkoffset, const __u16 lock_type, const int waitFlag) + struct file_lock *pLockData, const __u16 lock_type, + const int waitFlag) { struct smb_com_transaction2_sfi_req *pSMB = NULL; struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; @@ -1366,6 +1367,10 @@ CIFSSMBPosixLock(const int xid, struct c __u16 params, param_offset, offset, byte_count, count; cFYI(1, ("Posix Lock")); + + if(pLockData == NULL) + return EINVAL; + rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); if (rc) @@ -1404,10 +1409,10 @@ CIFSSMBPosixLock(const int xid, struct c parm_data->lock_type = cpu_to_le16(lock_type); if(waitFlag) - parm_data->lock_flags = 1; + parm_data->lock_flags = cpu_to_le16(1); parm_data->pid = cpu_to_le32(current->tgid); - parm_data->start = lkoffset; - parm_data->length = len; /* normalize negative numbers */ + parm_data->start = cpu_to_le64(pLockData->fl_start); + parm_data->length = cpu_to_le64(len); /* normalize negative numbers */ pSMB->DataOffset = cpu_to_le16(offset); pSMB->Fid = smb_file_id; @@ -1419,8 +1424,33 @@ CIFSSMBPosixLock(const int xid, struct c (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { cFYI(1, ("Send error in Posix Lock = %d", rc)); - } + } else if (get_flag) { + /* lock structure can be returned on get */ + __u16 data_offset; + __u16 data_count; + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) { + rc = -EIO; /* bad smb */ + goto plk_err_exit; + } + if(pLockData == NULL) { + rc = -EINVAL; + goto plk_err_exit; + } + data_offset = le16_to_cpu(pSMBr->t2.DataOffset); + data_count = le16_to_cpu(pSMBr->t2.DataCount); + if(data_count < sizeof(struct cifs_posix_lock)) { + rc = -EIO; + goto plk_err_exit; + } + parm_data = (struct cifs_posix_lock *) + ((char *)&pSMBr->hdr.Protocol + data_offset); + if(parm_data->lock_type == cpu_to_le16(CIFS_UNLCK)) + pLockData->fl_type = F_UNLCK; + } + +plk_err_exit: if (pSMB) cifs_small_buf_release(pSMB); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index d2ec806..bae1479 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2148,6 +2148,8 @@ CIFSSessSetup(unsigned int xid, struct c /* We look for obvious messed up bcc or strings in response so we do not go off the end since (at least) WIN2K and Windows XP have a major bug in not null terminating last Unicode string in response */ + if(ses->serverOS) + kfree(ses->serverOS); ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL); if(ses->serverOS == NULL) goto sesssetup_nomem; @@ -2160,6 +2162,8 @@ CIFSSessSetup(unsigned int xid, struct c if (remaining_words > 0) { len = UniStrnlen((wchar_t *)bcc_ptr, remaining_words-1); + if(ses->serverNOS) + kfree(ses->serverNOS); ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL); if(ses->serverNOS == NULL) goto sesssetup_nomem; @@ -2177,6 +2181,8 @@ CIFSSessSetup(unsigned int xid, struct c if (remaining_words > 0) { len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ + if(ses->serverDomain) + kfree(ses->serverDomain); ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL); if(ses->serverDomain == NULL) @@ -2187,15 +2193,22 @@ CIFSSessSetup(unsigned int xid, struct c ses->serverDomain[2*len] = 0; ses->serverDomain[1+(2*len)] = 0; } /* else no more room so create dummy domain string */ - else + else { + if(ses->serverDomain) + kfree(ses->serverDomain); ses->serverDomain = kzalloc(2, GFP_KERNEL); + } } else { /* no room so create dummy domain and NOS string */ /* if these kcallocs fail not much we can do, but better to not fail the sesssetup itself */ + if(ses->serverDomain) + kfree(ses->serverDomain); ses->serverDomain = kzalloc(2, GFP_KERNEL); + if(ses->serverNOS) + kfree(ses->serverNOS); ses->serverNOS = kzalloc(2, GFP_KERNEL); } @@ -2204,6 +2217,8 @@ CIFSSessSetup(unsigned int xid, struct c if (((long) bcc_ptr + len) - (long) pByteArea(smb_buffer_response) <= BCC(smb_buffer_response)) { + if(ses->serverOS) + kfree(ses->serverOS); ses->serverOS = kzalloc(len + 1,GFP_KERNEL); if(ses->serverOS == NULL) goto sesssetup_nomem; @@ -2214,6 +2229,8 @@ CIFSSessSetup(unsigned int xid, struct c bcc_ptr++; len = strnlen(bcc_ptr, 1024); + if(ses->serverNOS) + kfree(ses->serverNOS); ses->serverNOS = kzalloc(len + 1,GFP_KERNEL); if(ses->serverNOS == NULL) goto sesssetup_nomem; @@ -2223,6 +2240,8 @@ CIFSSessSetup(unsigned int xid, struct c bcc_ptr++; len = strnlen(bcc_ptr, 1024); + if(ses->serverDomain) + kfree(ses->serverDomain); ses->serverDomain = kzalloc(len + 1,GFP_KERNEL); if(ses->serverDomain == NULL) goto sesssetup_nomem; @@ -2427,6 +2446,8 @@ CIFSSpnegoSessSetup(unsigned int xid, st /* We look for obvious messed up bcc or strings in response so we do not go off the end since (at least) WIN2K and Windows XP have a major bug in not null terminating last Unicode string in response */ + if(ses->serverOS) + kfree(ses->serverOS); ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL); cifs_strfromUCS_le(ses->serverOS, @@ -2441,6 +2462,8 @@ CIFSSpnegoSessSetup(unsigned int xid, st len = UniStrnlen((wchar_t *)bcc_ptr, remaining_words - 1); + if(ses->serverNOS) + kfree(ses->serverNOS); ses->serverNOS = kzalloc(2 * (len + 1), GFP_KERNEL); @@ -2454,7 +2477,9 @@ CIFSSpnegoSessSetup(unsigned int xid, st remaining_words -= len + 1; if (remaining_words > 0) { len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); - /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ + /* last string not null terminated (e.g.Windows XP/2000) */ + if(ses->serverDomain) + kfree(ses->serverDomain); ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL); cifs_strfromUCS_le(ses->serverDomain, (__le16 *)bcc_ptr, @@ -2463,11 +2488,18 @@ CIFSSpnegoSessSetup(unsigned int xid, st ses->serverDomain[2*len] = 0; ses->serverDomain[1+(2*len)] = 0; } /* else no more room so create dummy domain string */ - else + else { + if(ses->serverDomain) + kfree(ses->serverDomain); ses->serverDomain = kzalloc(2,GFP_KERNEL); - } else { /* no room so create dummy domain and NOS string */ + } + } else {/* no room use dummy domain&NOS */ + if(ses->serverDomain) + kfree(ses->serverDomain); ses->serverDomain = kzalloc(2, GFP_KERNEL); + if(ses->serverNOS) + kfree(ses->serverNOS); ses->serverNOS = kzalloc(2, GFP_KERNEL); } } else { /* ASCII */ @@ -2476,6 +2508,8 @@ CIFSSpnegoSessSetup(unsigned int xid, st if (((long) bcc_ptr + len) - (long) pByteArea(smb_buffer_response) <= BCC(smb_buffer_response)) { + if(ses->serverOS) + kfree(ses->serverOS); ses->serverOS = kzalloc(len + 1, GFP_KERNEL); strncpy(ses->serverOS, bcc_ptr, len); @@ -2484,6 +2518,8 @@ CIFSSpnegoSessSetup(unsigned int xid, st bcc_ptr++; len = strnlen(bcc_ptr, 1024); + if(ses->serverNOS) + kfree(ses->serverNOS); ses->serverNOS = kzalloc(len + 1,GFP_KERNEL); strncpy(ses->serverNOS, bcc_ptr, len); bcc_ptr += len; @@ -2491,6 +2527,8 @@ CIFSSpnegoSessSetup(unsigned int xid, st bcc_ptr++; len = strnlen(bcc_ptr, 1024); + if(ses->serverDomain) + kfree(ses->serverDomain); ses->serverDomain = kzalloc(len + 1, GFP_KERNEL); strncpy(ses->serverDomain, bcc_ptr, len); bcc_ptr += len; @@ -2728,6 +2766,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned i /* We look for obvious messed up bcc or strings in response so we do not go off the end since (at least) WIN2K and Windows XP have a major bug in not null terminating last Unicode string in response */ + if(ses->serverOS) + kfree(ses->serverOS); ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL); cifs_strfromUCS_le(ses->serverOS, @@ -2743,6 +2783,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned i bcc_ptr, remaining_words - 1); + if(ses->serverNOS) + kfree(ses->serverNOS); ses->serverNOS = kzalloc(2 * (len + 1), GFP_KERNEL); @@ -2760,6 +2802,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned i if (remaining_words > 0) { len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ + if(ses->serverDomain) + kfree(ses->serverDomain); ses->serverDomain = kzalloc(2 * (len + @@ -2777,13 +2821,20 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned i [1 + (2 * len)] = 0; } /* else no more room so create dummy domain string */ - else + else { + if(ses->serverDomain) + kfree(ses->serverDomain); ses->serverDomain = kzalloc(2, GFP_KERNEL); + } } else { /* no room so create dummy domain and NOS string */ + if(ses->serverDomain); + kfree(ses->serverDomain); ses->serverDomain = kzalloc(2, GFP_KERNEL); + if(ses->serverNOS) + kfree(ses->serverNOS); ses->serverNOS = kzalloc(2, GFP_KERNEL); } @@ -2792,6 +2843,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned i if (((long) bcc_ptr + len) - (long) pByteArea(smb_buffer_response) <= BCC(smb_buffer_response)) { + if(ses->serverOS) + kfree(ses->serverOS); ses->serverOS = kzalloc(len + 1, GFP_KERNEL); @@ -2803,6 +2856,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned i bcc_ptr++; len = strnlen(bcc_ptr, 1024); + if(ses->serverNOS) + kfree(ses->serverNOS); ses->serverNOS = kzalloc(len + 1, GFP_KERNEL); @@ -2812,6 +2867,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned i bcc_ptr++; len = strnlen(bcc_ptr, 1024); + if(ses->serverDomain) + kfree(ses->serverDomain); ses->serverDomain = kzalloc(len + 1, GFP_KERNEL); @@ -3116,6 +3173,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xi /* We look for obvious messed up bcc or strings in response so we do not go off the end since (at least) WIN2K and Windows XP have a major bug in not null terminating last Unicode string in response */ + if(ses->serverOS) + kfree(ses->serverOS); ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL); cifs_strfromUCS_le(ses->serverOS, @@ -3131,6 +3190,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xi bcc_ptr, remaining_words - 1); + if(ses->serverNOS) + kfree(ses->serverNOS); ses->serverNOS = kzalloc(2 * (len + 1), GFP_KERNEL); @@ -3147,6 +3208,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xi if (remaining_words > 0) { len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); /* last string not always null terminated (e.g. for Windows XP & 2000) */ + if(ses->serverDomain) + kfree(ses->serverDomain); ses->serverDomain = kzalloc(2 * (len + @@ -3172,10 +3235,17 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xi len)] = 0; } /* else no more room so create dummy domain string */ - else + else { + if(ses->serverDomain) + kfree(ses->serverDomain); ses->serverDomain = kzalloc(2,GFP_KERNEL); + } } else { /* no room so create dummy domain and NOS string */ + if(ses->serverDomain) + kfree(ses->serverDomain); ses->serverDomain = kzalloc(2, GFP_KERNEL); + if(ses->serverNOS) + kfree(ses->serverNOS); ses->serverNOS = kzalloc(2, GFP_KERNEL); } } else { /* ASCII */ @@ -3183,6 +3253,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xi if (((long) bcc_ptr + len) - (long) pByteArea(smb_buffer_response) <= BCC(smb_buffer_response)) { + if(ses->serverOS) + kfree(ses->serverOS); ses->serverOS = kzalloc(len + 1,GFP_KERNEL); strncpy(ses->serverOS,bcc_ptr, len); @@ -3191,6 +3263,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xi bcc_ptr++; len = strnlen(bcc_ptr, 1024); + if(ses->serverNOS) + kfree(ses->serverNOS); ses->serverNOS = kzalloc(len+1,GFP_KERNEL); strncpy(ses->serverNOS, bcc_ptr, len); bcc_ptr += len; @@ -3198,6 +3272,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xi bcc_ptr++; len = strnlen(bcc_ptr, 1024); + if(ses->serverDomain) + kfree(ses->serverDomain); ses->serverDomain = kzalloc(len+1,GFP_KERNEL); strncpy(ses->serverDomain, bcc_ptr, len); bcc_ptr += len; @@ -3282,7 +3358,8 @@ CIFSTCon(unsigned int xid, struct cifsSe bcc_ptr++; /* align */ } - if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + if(ses->server->secMode & + (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; if (ses->capabilities & CAP_STATUS32) { @@ -3294,8 +3371,10 @@ CIFSTCon(unsigned int xid, struct cifsSe if (ses->capabilities & CAP_UNICODE) { smb_buffer->Flags2 |= SMBFLG2_UNICODE; length = - cifs_strtoUCS((__le16 *) bcc_ptr, tree, 100, nls_codepage); - bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */ + cifs_strtoUCS((__le16 *) bcc_ptr, tree, + 6 /* max utf8 char length in bytes */ * + (/* server len*/ + 256 /* share len */), nls_codepage); + bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */ bcc_ptr += 2; /* skip trailing null */ } else { /* ASCII */ strcpy(bcc_ptr, tree); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index e152bf6..5e59723 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -656,7 +656,7 @@ int cifs_lock(struct file *file, int cmd else posix_lock_type = CIFS_WRLCK; rc = CIFSSMBPosixLock(xid, pTcon, netfid, 1 /* get */, - length, pfLock->fl_start, + length, pfLock, posix_lock_type, wait_flag); FreeXid(xid); return rc; @@ -704,7 +704,7 @@ int cifs_lock(struct file *file, int cmd return -EOPNOTSUPP; } rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */, - length, pfLock->fl_start, + length, pfLock, posix_lock_type, wait_flag); } else rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, @@ -904,8 +904,10 @@ static ssize_t cifs_write(struct file *f if (rc != 0) break; } - if(experimEnabled || (pTcon->ses->server->secMode & - (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0) { + if(experimEnabled || (pTcon->ses->server && + ((pTcon->ses->server->secMode & + (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + == 0))) { struct kvec iov[2]; unsigned int len;