Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  [[CIFS] Pass truncate open flag through on file open in case setattr fails
  [CIFS] Fix typos in previous fix
  [CIFS] endian fix for new POSIX byte range lock support
  [CIFS] fix memory leak in cifs session info struct on reconnect
  [CIFS] ACPI suspend oops
  [CIFS] Do not limit the length of share names (was 100 for whole UNC name)
  [CIFS] Fix new POSIX Locking for setting lock_type correctly on unlock
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_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 @@
 			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 @@
 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 @@
 	__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 @@
 
 	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 @@
 			(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 @@
 /* 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 @@
 				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 @@
 					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 @@
 						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 @@
 				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 @@
 					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 @@
 					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 @@
 /* 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 @@
 						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 @@
 						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 @@
 							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 @@
 					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 @@
 						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 @@
 						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 @@
 /* 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 @@
 								 bcc_ptr,
 								 remaining_words
 								 - 1);
+						if(ses->serverNOS)
+							kfree(ses->serverNOS);
 						ses->serverNOS =
 						    kzalloc(2 * (len + 1),
 							    GFP_KERNEL);
@@ -2760,6 +2802,8 @@
 						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 @@
 								[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 @@
 					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 @@
 						bcc_ptr++;
 
 						len = strnlen(bcc_ptr, 1024);
+						if(ses->serverNOS)
+							kfree(ses->serverNOS);
 						ses->serverNOS =
 						    kzalloc(len + 1,
 							    GFP_KERNEL);
@@ -2812,6 +2867,8 @@
 						bcc_ptr++;
 
 						len = strnlen(bcc_ptr, 1024);
+						if(ses->serverDomain)
+							kfree(ses->serverDomain);
 						ses->serverDomain =
 						    kzalloc(len + 1,
 							    GFP_KERNEL);
@@ -3116,6 +3173,8 @@
 /* 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 @@
 								 bcc_ptr,
 								 remaining_words
 								 - 1);
+						if(ses->serverNOS)
+							kfree(ses->serverNOS);
 						ses->serverNOS =
 						    kzalloc(2 * (len + 1),
 							    GFP_KERNEL);
@@ -3147,6 +3208,8 @@
 						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 @@
 									  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 @@
 					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 @@
 						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 @@
 						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 @@
 		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 @@
 	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..e2b4ce1 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -84,6 +84,8 @@
 		return FILE_OVERWRITE_IF;
 	else if ((flags & O_CREAT) == O_CREAT)
 		return FILE_OPEN_IF;
+	else if ((flags & O_TRUNC) == O_TRUNC)
+		return FILE_OVERWRITE;
 	else
 		return FILE_OPEN;
 }
@@ -656,7 +658,7 @@
 			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 +706,7 @@
 			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 +906,10 @@
 				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;