aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifs_dfs_ref.c3
-rw-r--r--fs/cifs/cifs_unicode.c182
-rw-r--r--fs/cifs/cifsfs.c2
-rw-r--r--fs/cifs/cifsproto.h4
-rw-r--r--fs/cifs/cifssmb.c23
-rw-r--r--fs/cifs/connect.c3
-rw-r--r--fs/cifs/dir.c3
-rw-r--r--fs/cifs/file.c7
-rw-r--r--fs/cifs/inode.c31
-rw-r--r--fs/cifs/link.c3
-rw-r--r--fs/cifs/readdir.c2
-rw-r--r--fs/cifs/smb1ops.c3
-rw-r--r--fs/cifs/smb2pdu.c2
13 files changed, 194 insertions, 74 deletions
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index 430e0348c99e..7dc886c9a78f 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -24,6 +24,7 @@
24#include "cifsfs.h" 24#include "cifsfs.h"
25#include "dns_resolve.h" 25#include "dns_resolve.h"
26#include "cifs_debug.h" 26#include "cifs_debug.h"
27#include "cifs_unicode.h"
27 28
28static LIST_HEAD(cifs_dfs_automount_list); 29static LIST_HEAD(cifs_dfs_automount_list);
29 30
@@ -312,7 +313,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
312 xid = get_xid(); 313 xid = get_xid();
313 rc = get_dfs_path(xid, ses, full_path + 1, cifs_sb->local_nls, 314 rc = get_dfs_path(xid, ses, full_path + 1, cifs_sb->local_nls,
314 &num_referrals, &referrals, 315 &num_referrals, &referrals,
315 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 316 cifs_remap(cifs_sb));
316 free_xid(xid); 317 free_xid(xid);
317 318
318 cifs_put_tlink(tlink); 319 cifs_put_tlink(tlink);
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 0303c6793d90..5a53ac6b1e02 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -27,41 +27,6 @@
27#include "cifsglob.h" 27#include "cifsglob.h"
28#include "cifs_debug.h" 28#include "cifs_debug.h"
29 29
30/*
31 * cifs_utf16_bytes - how long will a string be after conversion?
32 * @utf16 - pointer to input string
33 * @maxbytes - don't go past this many bytes of input string
34 * @codepage - destination codepage
35 *
36 * Walk a utf16le string and return the number of bytes that the string will
37 * be after being converted to the given charset, not including any null
38 * termination required. Don't walk past maxbytes in the source buffer.
39 */
40int
41cifs_utf16_bytes(const __le16 *from, int maxbytes,
42 const struct nls_table *codepage)
43{
44 int i;
45 int charlen, outlen = 0;
46 int maxwords = maxbytes / 2;
47 char tmp[NLS_MAX_CHARSET_SIZE];
48 __u16 ftmp;
49
50 for (i = 0; i < maxwords; i++) {
51 ftmp = get_unaligned_le16(&from[i]);
52 if (ftmp == 0)
53 break;
54
55 charlen = codepage->uni2char(ftmp, tmp, NLS_MAX_CHARSET_SIZE);
56 if (charlen > 0)
57 outlen += charlen;
58 else
59 outlen++;
60 }
61
62 return outlen;
63}
64
65int cifs_remap(struct cifs_sb_info *cifs_sb) 30int cifs_remap(struct cifs_sb_info *cifs_sb)
66{ 31{
67 int map_type; 32 int map_type;
@@ -155,10 +120,13 @@ convert_sfm_char(const __u16 src_char, char *target)
155 * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE). 120 * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE).
156 */ 121 */
157static int 122static int
158cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, 123cifs_mapchar(char *target, const __u16 *from, const struct nls_table *cp,
159 int maptype) 124 int maptype)
160{ 125{
161 int len = 1; 126 int len = 1;
127 __u16 src_char;
128
129 src_char = *from;
162 130
163 if ((maptype == SFM_MAP_UNI_RSVD) && convert_sfm_char(src_char, target)) 131 if ((maptype == SFM_MAP_UNI_RSVD) && convert_sfm_char(src_char, target))
164 return len; 132 return len;
@@ -168,10 +136,23 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp,
168 136
169 /* if character not one of seven in special remap set */ 137 /* if character not one of seven in special remap set */
170 len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE); 138 len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE);
171 if (len <= 0) { 139 if (len <= 0)
172 *target = '?'; 140 goto surrogate_pair;
173 len = 1; 141
174 } 142 return len;
143
144surrogate_pair:
145 /* convert SURROGATE_PAIR and IVS */
146 if (strcmp(cp->charset, "utf8"))
147 goto unknown;
148 len = utf16s_to_utf8s(from, 3, UTF16_LITTLE_ENDIAN, target, 6);
149 if (len <= 0)
150 goto unknown;
151 return len;
152
153unknown:
154 *target = '?';
155 len = 1;
175 return len; 156 return len;
176} 157}
177 158
@@ -206,7 +187,7 @@ cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
206 int nullsize = nls_nullsize(codepage); 187 int nullsize = nls_nullsize(codepage);
207 int fromwords = fromlen / 2; 188 int fromwords = fromlen / 2;
208 char tmp[NLS_MAX_CHARSET_SIZE]; 189 char tmp[NLS_MAX_CHARSET_SIZE];
209 __u16 ftmp; 190 __u16 ftmp[3]; /* ftmp[3] = 3array x 2bytes = 6bytes UTF-16 */
210 191
211 /* 192 /*
212 * because the chars can be of varying widths, we need to take care 193 * because the chars can be of varying widths, we need to take care
@@ -217,9 +198,17 @@ cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
217 safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize); 198 safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize);
218 199
219 for (i = 0; i < fromwords; i++) { 200 for (i = 0; i < fromwords; i++) {
220 ftmp = get_unaligned_le16(&from[i]); 201 ftmp[0] = get_unaligned_le16(&from[i]);
221 if (ftmp == 0) 202 if (ftmp[0] == 0)
222 break; 203 break;
204 if (i + 1 < fromwords)
205 ftmp[1] = get_unaligned_le16(&from[i + 1]);
206 else
207 ftmp[1] = 0;
208 if (i + 2 < fromwords)
209 ftmp[2] = get_unaligned_le16(&from[i + 2]);
210 else
211 ftmp[2] = 0;
223 212
224 /* 213 /*
225 * check to see if converting this character might make the 214 * check to see if converting this character might make the
@@ -234,6 +223,17 @@ cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
234 /* put converted char into 'to' buffer */ 223 /* put converted char into 'to' buffer */
235 charlen = cifs_mapchar(&to[outlen], ftmp, codepage, map_type); 224 charlen = cifs_mapchar(&to[outlen], ftmp, codepage, map_type);
236 outlen += charlen; 225 outlen += charlen;
226
227 /* charlen (=bytes of UTF-8 for 1 character)
228 * 4bytes UTF-8(surrogate pair) is charlen=4
229 * (4bytes UTF-16 code)
230 * 7-8bytes UTF-8(IVS) is charlen=3+4 or 4+4
231 * (2 UTF-8 pairs divided to 2 UTF-16 pairs) */
232 if (charlen == 4)
233 i++;
234 else if (charlen >= 5)
235 /* 5-6bytes UTF-8 */
236 i += 2;
237 } 237 }
238 238
239 /* properly null-terminate string */ 239 /* properly null-terminate string */
@@ -296,6 +296,46 @@ success:
296} 296}
297 297
298/* 298/*
299 * cifs_utf16_bytes - how long will a string be after conversion?
300 * @utf16 - pointer to input string
301 * @maxbytes - don't go past this many bytes of input string
302 * @codepage - destination codepage
303 *
304 * Walk a utf16le string and return the number of bytes that the string will
305 * be after being converted to the given charset, not including any null
306 * termination required. Don't walk past maxbytes in the source buffer.
307 */
308int
309cifs_utf16_bytes(const __le16 *from, int maxbytes,
310 const struct nls_table *codepage)
311{
312 int i;
313 int charlen, outlen = 0;
314 int maxwords = maxbytes / 2;
315 char tmp[NLS_MAX_CHARSET_SIZE];
316 __u16 ftmp[3];
317
318 for (i = 0; i < maxwords; i++) {
319 ftmp[0] = get_unaligned_le16(&from[i]);
320 if (ftmp[0] == 0)
321 break;
322 if (i + 1 < maxwords)
323 ftmp[1] = get_unaligned_le16(&from[i + 1]);
324 else
325 ftmp[1] = 0;
326 if (i + 2 < maxwords)
327 ftmp[2] = get_unaligned_le16(&from[i + 2]);
328 else
329 ftmp[2] = 0;
330
331 charlen = cifs_mapchar(tmp, ftmp, codepage, NO_MAP_UNI_RSVD);
332 outlen += charlen;
333 }
334
335 return outlen;
336}
337
338/*
299 * cifs_strndup_from_utf16 - copy a string from wire format to the local 339 * cifs_strndup_from_utf16 - copy a string from wire format to the local
300 * codepage 340 * codepage
301 * @src - source string 341 * @src - source string
@@ -409,10 +449,15 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
409 char src_char; 449 char src_char;
410 __le16 dst_char; 450 __le16 dst_char;
411 wchar_t tmp; 451 wchar_t tmp;
452 wchar_t *wchar_to; /* UTF-16 */
453 int ret;
454 unicode_t u;
412 455
413 if (map_chars == NO_MAP_UNI_RSVD) 456 if (map_chars == NO_MAP_UNI_RSVD)
414 return cifs_strtoUTF16(target, source, PATH_MAX, cp); 457 return cifs_strtoUTF16(target, source, PATH_MAX, cp);
415 458
459 wchar_to = kzalloc(6, GFP_KERNEL);
460
416 for (i = 0; i < srclen; j++) { 461 for (i = 0; i < srclen; j++) {
417 src_char = source[i]; 462 src_char = source[i];
418 charlen = 1; 463 charlen = 1;
@@ -441,11 +486,55 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
441 * if no match, use question mark, which at least in 486 * if no match, use question mark, which at least in
442 * some cases serves as wild card 487 * some cases serves as wild card
443 */ 488 */
444 if (charlen < 1) { 489 if (charlen > 0)
445 dst_char = cpu_to_le16(0x003f); 490 goto ctoUTF16;
446 charlen = 1; 491
492 /* convert SURROGATE_PAIR */
493 if (strcmp(cp->charset, "utf8") || !wchar_to)
494 goto unknown;
495 if (*(source + i) & 0x80) {
496 charlen = utf8_to_utf32(source + i, 6, &u);
497 if (charlen < 0)
498 goto unknown;
499 } else
500 goto unknown;
501 ret = utf8s_to_utf16s(source + i, charlen,
502 UTF16_LITTLE_ENDIAN,
503 wchar_to, 6);
504 if (ret < 0)
505 goto unknown;
506
507 i += charlen;
508 dst_char = cpu_to_le16(*wchar_to);
509 if (charlen <= 3)
510 /* 1-3bytes UTF-8 to 2bytes UTF-16 */
511 put_unaligned(dst_char, &target[j]);
512 else if (charlen == 4) {
513 /* 4bytes UTF-8(surrogate pair) to 4bytes UTF-16
514 * 7-8bytes UTF-8(IVS) divided to 2 UTF-16
515 * (charlen=3+4 or 4+4) */
516 put_unaligned(dst_char, &target[j]);
517 dst_char = cpu_to_le16(*(wchar_to + 1));
518 j++;
519 put_unaligned(dst_char, &target[j]);
520 } else if (charlen >= 5) {
521 /* 5-6bytes UTF-8 to 6bytes UTF-16 */
522 put_unaligned(dst_char, &target[j]);
523 dst_char = cpu_to_le16(*(wchar_to + 1));
524 j++;
525 put_unaligned(dst_char, &target[j]);
526 dst_char = cpu_to_le16(*(wchar_to + 2));
527 j++;
528 put_unaligned(dst_char, &target[j]);
447 } 529 }
530 continue;
531
532unknown:
533 dst_char = cpu_to_le16(0x003f);
534 charlen = 1;
448 } 535 }
536
537ctoUTF16:
449 /* 538 /*
450 * character may take more than one byte in the source string, 539 * character may take more than one byte in the source string,
451 * but will take exactly two bytes in the target string 540 * but will take exactly two bytes in the target string
@@ -456,6 +545,7 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
456 545
457ctoUTF16_out: 546ctoUTF16_out:
458 put_unaligned(0, &target[j]); /* Null terminate target unicode string */ 547 put_unaligned(0, &target[j]); /* Null terminate target unicode string */
548 kfree(wchar_to);
459 return j; 549 return j;
460} 550}
461 551
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index f5089bde3635..0a9fb6b53126 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -469,6 +469,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
469 seq_puts(s, ",nouser_xattr"); 469 seq_puts(s, ",nouser_xattr");
470 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) 470 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
471 seq_puts(s, ",mapchars"); 471 seq_puts(s, ",mapchars");
472 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR)
473 seq_puts(s, ",mapposix");
472 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) 474 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
473 seq_puts(s, ",sfu"); 475 seq_puts(s, ",sfu");
474 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 476 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index c31ce98c1704..c63fd1dde25b 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -361,11 +361,11 @@ extern int CIFSUnixCreateHardLink(const unsigned int xid,
361extern int CIFSUnixCreateSymLink(const unsigned int xid, 361extern int CIFSUnixCreateSymLink(const unsigned int xid,
362 struct cifs_tcon *tcon, 362 struct cifs_tcon *tcon,
363 const char *fromName, const char *toName, 363 const char *fromName, const char *toName,
364 const struct nls_table *nls_codepage); 364 const struct nls_table *nls_codepage, int remap);
365extern int CIFSSMBUnixQuerySymLink(const unsigned int xid, 365extern int CIFSSMBUnixQuerySymLink(const unsigned int xid,
366 struct cifs_tcon *tcon, 366 struct cifs_tcon *tcon,
367 const unsigned char *searchName, char **syminfo, 367 const unsigned char *searchName, char **syminfo,
368 const struct nls_table *nls_codepage); 368 const struct nls_table *nls_codepage, int remap);
369extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, 369extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
370 __u16 fid, char **symlinkinfo, 370 __u16 fid, char **symlinkinfo,
371 const struct nls_table *nls_codepage); 371 const struct nls_table *nls_codepage);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 84650a51c7c4..f26ffbfc64d8 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2784,7 +2784,7 @@ copyRetry:
2784int 2784int
2785CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon, 2785CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon,
2786 const char *fromName, const char *toName, 2786 const char *fromName, const char *toName,
2787 const struct nls_table *nls_codepage) 2787 const struct nls_table *nls_codepage, int remap)
2788{ 2788{
2789 TRANSACTION2_SPI_REQ *pSMB = NULL; 2789 TRANSACTION2_SPI_REQ *pSMB = NULL;
2790 TRANSACTION2_SPI_RSP *pSMBr = NULL; 2790 TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -2804,9 +2804,9 @@ createSymLinkRetry:
2804 2804
2805 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2805 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2806 name_len = 2806 name_len =
2807 cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName, 2807 cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName,
2808 /* find define for this maxpathcomponent */ 2808 /* find define for this maxpathcomponent */
2809 PATH_MAX, nls_codepage); 2809 PATH_MAX, nls_codepage, remap);
2810 name_len++; /* trailing null */ 2810 name_len++; /* trailing null */
2811 name_len *= 2; 2811 name_len *= 2;
2812 2812
@@ -2828,9 +2828,9 @@ createSymLinkRetry:
2828 data_offset = (char *) (&pSMB->hdr.Protocol) + offset; 2828 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
2829 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 2829 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2830 name_len_target = 2830 name_len_target =
2831 cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX 2831 cifsConvertToUTF16((__le16 *) data_offset, toName,
2832 /* find define for this maxpathcomponent */ 2832 /* find define for this maxpathcomponent */
2833 , nls_codepage); 2833 PATH_MAX, nls_codepage, remap);
2834 name_len_target++; /* trailing null */ 2834 name_len_target++; /* trailing null */
2835 name_len_target *= 2; 2835 name_len_target *= 2;
2836 } else { /* BB improve the check for buffer overruns BB */ 2836 } else { /* BB improve the check for buffer overruns BB */
@@ -3034,7 +3034,7 @@ winCreateHardLinkRetry:
3034int 3034int
3035CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, 3035CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
3036 const unsigned char *searchName, char **symlinkinfo, 3036 const unsigned char *searchName, char **symlinkinfo,
3037 const struct nls_table *nls_codepage) 3037 const struct nls_table *nls_codepage, int remap)
3038{ 3038{
3039/* SMB_QUERY_FILE_UNIX_LINK */ 3039/* SMB_QUERY_FILE_UNIX_LINK */
3040 TRANSACTION2_QPI_REQ *pSMB = NULL; 3040 TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -3055,8 +3055,9 @@ querySymLinkRetry:
3055 3055
3056 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 3056 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3057 name_len = 3057 name_len =
3058 cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName, 3058 cifsConvertToUTF16((__le16 *) pSMB->FileName,
3059 PATH_MAX, nls_codepage); 3059 searchName, PATH_MAX, nls_codepage,
3060 remap);
3060 name_len++; /* trailing null */ 3061 name_len++; /* trailing null */
3061 name_len *= 2; 3062 name_len *= 2;
3062 } else { /* BB improve the check for buffer overruns BB */ 3063 } else { /* BB improve the check for buffer overruns BB */
@@ -4917,7 +4918,7 @@ getDFSRetry:
4917 strncpy(pSMB->RequestFileName, search_name, name_len); 4918 strncpy(pSMB->RequestFileName, search_name, name_len);
4918 } 4919 }
4919 4920
4920 if (ses->server && ses->server->sign) 4921 if (ses->server->sign)
4921 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; 4922 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4922 4923
4923 pSMB->hdr.Uid = ses->Suid; 4924 pSMB->hdr.Uid = ses->Suid;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index f3bfe08e177b..8383d5ea4202 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -386,6 +386,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
386 rc = generic_ip_connect(server); 386 rc = generic_ip_connect(server);
387 if (rc) { 387 if (rc) {
388 cifs_dbg(FYI, "reconnect error %d\n", rc); 388 cifs_dbg(FYI, "reconnect error %d\n", rc);
389 mutex_unlock(&server->srv_mutex);
389 msleep(3000); 390 msleep(3000);
390 } else { 391 } else {
391 atomic_inc(&tcpSesReconnectCount); 392 atomic_inc(&tcpSesReconnectCount);
@@ -393,8 +394,8 @@ cifs_reconnect(struct TCP_Server_Info *server)
393 if (server->tcpStatus != CifsExiting) 394 if (server->tcpStatus != CifsExiting)
394 server->tcpStatus = CifsNeedNegotiate; 395 server->tcpStatus = CifsNeedNegotiate;
395 spin_unlock(&GlobalMid_Lock); 396 spin_unlock(&GlobalMid_Lock);
397 mutex_unlock(&server->srv_mutex);
396 } 398 }
397 mutex_unlock(&server->srv_mutex);
398 } while (server->tcpStatus == CifsNeedReconnect); 399 } while (server->tcpStatus == CifsNeedReconnect);
399 400
400 return rc; 401 return rc;
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 338d56936f6a..c3eb998a99bd 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -620,8 +620,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
620 } 620 }
621 rc = CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, 621 rc = CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
622 cifs_sb->local_nls, 622 cifs_sb->local_nls,
623 cifs_sb->mnt_cifs_flags & 623 cifs_remap(cifs_sb));
624 CIFS_MOUNT_MAP_SPECIAL_CHR);
625 if (rc) 624 if (rc)
626 goto mknod_out; 625 goto mknod_out;
627 626
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index cafbf10521d5..3f50cee79df9 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -140,8 +140,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
140 posix_flags = cifs_posix_convert_flags(f_flags); 140 posix_flags = cifs_posix_convert_flags(f_flags);
141 rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data, 141 rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data,
142 poplock, full_path, cifs_sb->local_nls, 142 poplock, full_path, cifs_sb->local_nls,
143 cifs_sb->mnt_cifs_flags & 143 cifs_remap(cifs_sb));
144 CIFS_MOUNT_MAP_SPECIAL_CHR);
145 cifs_put_tlink(tlink); 144 cifs_put_tlink(tlink);
146 145
147 if (rc) 146 if (rc)
@@ -1553,8 +1552,8 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
1553 rc = server->ops->mand_unlock_range(cfile, flock, xid); 1552 rc = server->ops->mand_unlock_range(cfile, flock, xid);
1554 1553
1555out: 1554out:
1556 if (flock->fl_flags & FL_POSIX) 1555 if (flock->fl_flags & FL_POSIX && !rc)
1557 posix_lock_file_wait(file, flock); 1556 rc = posix_lock_file_wait(file, flock);
1558 return rc; 1557 return rc;
1559} 1558}
1560 1559
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 55b58112d122..f621b44cb800 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -373,8 +373,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
373 373
374 /* could have done a find first instead but this returns more info */ 374 /* could have done a find first instead but this returns more info */
375 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, 375 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
376 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 376 cifs_sb->local_nls, cifs_remap(cifs_sb));
377 CIFS_MOUNT_MAP_SPECIAL_CHR);
378 cifs_put_tlink(tlink); 377 cifs_put_tlink(tlink);
379 378
380 if (!rc) { 379 if (!rc) {
@@ -402,9 +401,25 @@ int cifs_get_inode_info_unix(struct inode **pinode,
402 rc = -ENOMEM; 401 rc = -ENOMEM;
403 } else { 402 } else {
404 /* we already have inode, update it */ 403 /* we already have inode, update it */
404
405 /* if uniqueid is different, return error */
406 if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
407 CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
408 rc = -ESTALE;
409 goto cgiiu_exit;
410 }
411
412 /* if filetype is different, return error */
413 if (unlikely(((*pinode)->i_mode & S_IFMT) !=
414 (fattr.cf_mode & S_IFMT))) {
415 rc = -ESTALE;
416 goto cgiiu_exit;
417 }
418
405 cifs_fattr_to_inode(*pinode, &fattr); 419 cifs_fattr_to_inode(*pinode, &fattr);
406 } 420 }
407 421
422cgiiu_exit:
408 return rc; 423 return rc;
409} 424}
410 425
@@ -839,6 +854,15 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
839 if (!*inode) 854 if (!*inode)
840 rc = -ENOMEM; 855 rc = -ENOMEM;
841 } else { 856 } else {
857 /* we already have inode, update it */
858
859 /* if filetype is different, return error */
860 if (unlikely(((*inode)->i_mode & S_IFMT) !=
861 (fattr.cf_mode & S_IFMT))) {
862 rc = -ESTALE;
863 goto cgii_exit;
864 }
865
842 cifs_fattr_to_inode(*inode, &fattr); 866 cifs_fattr_to_inode(*inode, &fattr);
843 } 867 }
844 868
@@ -2215,8 +2239,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
2215 pTcon = tlink_tcon(tlink); 2239 pTcon = tlink_tcon(tlink);
2216 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, 2240 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
2217 cifs_sb->local_nls, 2241 cifs_sb->local_nls,
2218 cifs_sb->mnt_cifs_flags & 2242 cifs_remap(cifs_sb));
2219 CIFS_MOUNT_MAP_SPECIAL_CHR);
2220 cifs_put_tlink(tlink); 2243 cifs_put_tlink(tlink);
2221 } 2244 }
2222 2245
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 252e672d5604..e6c707cc62b3 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -717,7 +717,8 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
717 rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname); 717 rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname);
718 else if (pTcon->unix_ext) 718 else if (pTcon->unix_ext)
719 rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, 719 rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
720 cifs_sb->local_nls); 720 cifs_sb->local_nls,
721 cifs_remap(cifs_sb));
721 /* else 722 /* else
722 rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName, 723 rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,
723 cifs_sb_target->local_nls); */ 724 cifs_sb_target->local_nls); */
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index b4a47237486b..b1eede3678a9 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -90,6 +90,8 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
90 if (dentry) { 90 if (dentry) {
91 inode = d_inode(dentry); 91 inode = d_inode(dentry);
92 if (inode) { 92 if (inode) {
93 if (d_mountpoint(dentry))
94 goto out;
93 /* 95 /*
94 * If we're generating inode numbers, then we don't 96 * If we're generating inode numbers, then we don't
95 * want to clobber the existing one with the one that 97 * want to clobber the existing one with the one that
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 7bfdd6066276..fc537c29044e 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -960,7 +960,8 @@ cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
960 /* Check for unix extensions */ 960 /* Check for unix extensions */
961 if (cap_unix(tcon->ses)) { 961 if (cap_unix(tcon->ses)) {
962 rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path, 962 rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path,
963 cifs_sb->local_nls); 963 cifs_sb->local_nls,
964 cifs_remap(cifs_sb));
964 if (rc == -EREMOTE) 965 if (rc == -EREMOTE)
965 rc = cifs_unix_dfs_readlink(xid, tcon, full_path, 966 rc = cifs_unix_dfs_readlink(xid, tcon, full_path,
966 target_path, 967 target_path,
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 65cd7a84c8bc..54cbe19d9c08 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -110,7 +110,7 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ ,
110 110
111 /* GLOBAL_CAP_LARGE_MTU will only be set if dialect > SMB2.02 */ 111 /* GLOBAL_CAP_LARGE_MTU will only be set if dialect > SMB2.02 */
112 /* See sections 2.2.4 and 3.2.4.1.5 of MS-SMB2 */ 112 /* See sections 2.2.4 and 3.2.4.1.5 of MS-SMB2 */
113 if ((tcon->ses) && 113 if ((tcon->ses) && (tcon->ses->server) &&
114 (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) 114 (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
115 hdr->CreditCharge = cpu_to_le16(1); 115 hdr->CreditCharge = cpu_to_le16(1);
116 /* else CreditCharge MBZ */ 116 /* else CreditCharge MBZ */