diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-18 16:39:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-18 16:39:19 -0400 |
commit | 9272f2dc3956c6b6c4335de51bc897fa3b981584 (patch) | |
tree | 0fed79884531f07bbc3abeca876d3a8b60f653b3 /fs | |
parent | e83e43237236ba89316e97a3743b5bd585726e47 (diff) | |
parent | ff273cb879fbc6cd3c5d03a56cfc33f5830e2837 (diff) |
Merge branch 'for-linus' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs/smb3 updates from Steve French:
"Improved SMB3 support (symlink and device emulation, and remapping by
default the 7 reserved posix characters) and a workaround for cifs
mounts to Mac (working around a commonly encountered Mac server bug)"
* 'for-linus' of git://git.samba.org/sfrench/cifs-2.6:
[CIFS] Remove obsolete comment
Check minimum response length on query_network_interface
Workaround Mac server problem
Remap reserved posix characters by default (part 3/3)
Allow conversion of characters in Mac remap range (part 2)
Allow conversion of characters in Mac remap range. Part 1
mfsymlinks support for SMB2.1/SMB3. Part 2 query symlink
Add mfsymlinks support for SMB2.1/SMB3. Part 1 create symlink
Allow mknod and mkfifo on SMB2/SMB3 mounts
add defines for two new file attributes
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifs_fs_sb.h | 1 | ||||
-rw-r--r-- | fs/cifs/cifs_unicode.c | 203 | ||||
-rw-r--r-- | fs/cifs/cifs_unicode.h | 31 | ||||
-rw-r--r-- | fs/cifs/cifsencrypt.c | 2 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 6 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 16 | ||||
-rw-r--r-- | fs/cifs/connect.c | 46 | ||||
-rw-r--r-- | fs/cifs/dir.c | 22 | ||||
-rw-r--r-- | fs/cifs/file.c | 6 | ||||
-rw-r--r-- | fs/cifs/inode.c | 57 | ||||
-rw-r--r-- | fs/cifs/link.c | 145 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 8 | ||||
-rw-r--r-- | fs/cifs/smb1ops.c | 33 | ||||
-rw-r--r-- | fs/cifs/smb2misc.c | 12 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 27 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 2 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.h | 2 | ||||
-rw-r--r-- | fs/cifs/smb2proto.h | 8 | ||||
-rw-r--r-- | fs/cifs/smbencrypt.c | 1 | ||||
-rw-r--r-- | fs/cifs/xattr.c | 32 |
20 files changed, 489 insertions, 171 deletions
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index 9409fa10bd5c..3182273a3407 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
@@ -45,6 +45,7 @@ | |||
45 | #define CIFS_MOUNT_POSIXACL 0x100000 /* mirror of MS_POSIXACL in mnt_cifs_flags */ | 45 | #define CIFS_MOUNT_POSIXACL 0x100000 /* mirror of MS_POSIXACL in mnt_cifs_flags */ |
46 | #define CIFS_MOUNT_CIFS_BACKUPUID 0x200000 /* backup intent bit for a user */ | 46 | #define CIFS_MOUNT_CIFS_BACKUPUID 0x200000 /* backup intent bit for a user */ |
47 | #define CIFS_MOUNT_CIFS_BACKUPGID 0x400000 /* backup intent bit for a group */ | 47 | #define CIFS_MOUNT_CIFS_BACKUPGID 0x400000 /* backup intent bit for a group */ |
48 | #define CIFS_MOUNT_MAP_SFM_CHR 0x800000 /* SFM/MAC mapping for illegal chars */ | ||
48 | 49 | ||
49 | struct cifs_sb_info { | 50 | struct cifs_sb_info { |
50 | struct rb_root tlink_tree; | 51 | struct rb_root tlink_tree; |
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index 15e9505aa35f..0303c6793d90 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include "cifs_fs_sb.h" | ||
23 | #include "cifs_unicode.h" | 24 | #include "cifs_unicode.h" |
24 | #include "cifs_uniupr.h" | 25 | #include "cifs_uniupr.h" |
25 | #include "cifspdu.h" | 26 | #include "cifspdu.h" |
@@ -61,26 +62,24 @@ cifs_utf16_bytes(const __le16 *from, int maxbytes, | |||
61 | return outlen; | 62 | return outlen; |
62 | } | 63 | } |
63 | 64 | ||
64 | /* | 65 | int cifs_remap(struct cifs_sb_info *cifs_sb) |
65 | * cifs_mapchar - convert a host-endian char to proper char in codepage | ||
66 | * @target - where converted character should be copied | ||
67 | * @src_char - 2 byte host-endian source character | ||
68 | * @cp - codepage to which character should be converted | ||
69 | * @mapchar - should character be mapped according to mapchars mount option? | ||
70 | * | ||
71 | * This function handles the conversion of a single character. It is the | ||
72 | * responsibility of the caller to ensure that the target buffer is large | ||
73 | * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE). | ||
74 | */ | ||
75 | static int | ||
76 | cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, | ||
77 | bool mapchar) | ||
78 | { | 66 | { |
79 | int len = 1; | 67 | int map_type; |
68 | |||
69 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR) | ||
70 | map_type = SFM_MAP_UNI_RSVD; | ||
71 | else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) | ||
72 | map_type = SFU_MAP_UNI_RSVD; | ||
73 | else | ||
74 | map_type = NO_MAP_UNI_RSVD; | ||
80 | 75 | ||
81 | if (!mapchar) | 76 | return map_type; |
82 | goto cp_convert; | 77 | } |
83 | 78 | ||
79 | /* Convert character using the SFU - "Services for Unix" remapping range */ | ||
80 | static bool | ||
81 | convert_sfu_char(const __u16 src_char, char *target) | ||
82 | { | ||
84 | /* | 83 | /* |
85 | * BB: Cannot handle remapping UNI_SLASH until all the calls to | 84 | * BB: Cannot handle remapping UNI_SLASH until all the calls to |
86 | * build_path_from_dentry are modified, as they use slash as | 85 | * build_path_from_dentry are modified, as they use slash as |
@@ -106,19 +105,74 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, | |||
106 | *target = '<'; | 105 | *target = '<'; |
107 | break; | 106 | break; |
108 | default: | 107 | default: |
109 | goto cp_convert; | 108 | return false; |
110 | } | 109 | } |
110 | return true; | ||
111 | } | ||
112 | |||
113 | /* Convert character using the SFM - "Services for Mac" remapping range */ | ||
114 | static bool | ||
115 | convert_sfm_char(const __u16 src_char, char *target) | ||
116 | { | ||
117 | switch (src_char) { | ||
118 | case SFM_COLON: | ||
119 | *target = ':'; | ||
120 | break; | ||
121 | case SFM_ASTERISK: | ||
122 | *target = '*'; | ||
123 | break; | ||
124 | case SFM_QUESTION: | ||
125 | *target = '?'; | ||
126 | break; | ||
127 | case SFM_PIPE: | ||
128 | *target = '|'; | ||
129 | break; | ||
130 | case SFM_GRTRTHAN: | ||
131 | *target = '>'; | ||
132 | break; | ||
133 | case SFM_LESSTHAN: | ||
134 | *target = '<'; | ||
135 | break; | ||
136 | case SFM_SLASH: | ||
137 | *target = '\\'; | ||
138 | break; | ||
139 | default: | ||
140 | return false; | ||
141 | } | ||
142 | return true; | ||
143 | } | ||
111 | 144 | ||
112 | out: | ||
113 | return len; | ||
114 | 145 | ||
115 | cp_convert: | 146 | /* |
147 | * cifs_mapchar - convert a host-endian char to proper char in codepage | ||
148 | * @target - where converted character should be copied | ||
149 | * @src_char - 2 byte host-endian source character | ||
150 | * @cp - codepage to which character should be converted | ||
151 | * @map_type - How should the 7 NTFS/SMB reserved characters be mapped to UCS2? | ||
152 | * | ||
153 | * This function handles the conversion of a single character. It is the | ||
154 | * responsibility of the caller to ensure that the target buffer is large | ||
155 | * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE). | ||
156 | */ | ||
157 | static int | ||
158 | cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, | ||
159 | int maptype) | ||
160 | { | ||
161 | int len = 1; | ||
162 | |||
163 | if ((maptype == SFM_MAP_UNI_RSVD) && convert_sfm_char(src_char, target)) | ||
164 | return len; | ||
165 | else if ((maptype == SFU_MAP_UNI_RSVD) && | ||
166 | convert_sfu_char(src_char, target)) | ||
167 | return len; | ||
168 | |||
169 | /* if character not one of seven in special remap set */ | ||
116 | len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE); | 170 | len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE); |
117 | if (len <= 0) { | 171 | if (len <= 0) { |
118 | *target = '?'; | 172 | *target = '?'; |
119 | len = 1; | 173 | len = 1; |
120 | } | 174 | } |
121 | goto out; | 175 | return len; |
122 | } | 176 | } |
123 | 177 | ||
124 | /* | 178 | /* |
@@ -145,7 +199,7 @@ cp_convert: | |||
145 | */ | 199 | */ |
146 | int | 200 | int |
147 | cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen, | 201 | cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen, |
148 | const struct nls_table *codepage, bool mapchar) | 202 | const struct nls_table *codepage, int map_type) |
149 | { | 203 | { |
150 | int i, charlen, safelen; | 204 | int i, charlen, safelen; |
151 | int outlen = 0; | 205 | int outlen = 0; |
@@ -172,13 +226,13 @@ cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen, | |||
172 | * conversion bleed into the null terminator | 226 | * conversion bleed into the null terminator |
173 | */ | 227 | */ |
174 | if (outlen >= safelen) { | 228 | if (outlen >= safelen) { |
175 | charlen = cifs_mapchar(tmp, ftmp, codepage, mapchar); | 229 | charlen = cifs_mapchar(tmp, ftmp, codepage, map_type); |
176 | if ((outlen + charlen) > (tolen - nullsize)) | 230 | if ((outlen + charlen) > (tolen - nullsize)) |
177 | break; | 231 | break; |
178 | } | 232 | } |
179 | 233 | ||
180 | /* put converted char into 'to' buffer */ | 234 | /* put converted char into 'to' buffer */ |
181 | charlen = cifs_mapchar(&to[outlen], ftmp, codepage, mapchar); | 235 | charlen = cifs_mapchar(&to[outlen], ftmp, codepage, map_type); |
182 | outlen += charlen; | 236 | outlen += charlen; |
183 | } | 237 | } |
184 | 238 | ||
@@ -267,7 +321,7 @@ cifs_strndup_from_utf16(const char *src, const int maxlen, | |||
267 | if (!dst) | 321 | if (!dst) |
268 | return NULL; | 322 | return NULL; |
269 | cifs_from_utf16(dst, (__le16 *) src, len, maxlen, codepage, | 323 | cifs_from_utf16(dst, (__le16 *) src, len, maxlen, codepage, |
270 | false); | 324 | NO_MAP_UNI_RSVD); |
271 | } else { | 325 | } else { |
272 | len = strnlen(src, maxlen); | 326 | len = strnlen(src, maxlen); |
273 | len++; | 327 | len++; |
@@ -280,6 +334,66 @@ cifs_strndup_from_utf16(const char *src, const int maxlen, | |||
280 | return dst; | 334 | return dst; |
281 | } | 335 | } |
282 | 336 | ||
337 | static __le16 convert_to_sfu_char(char src_char) | ||
338 | { | ||
339 | __le16 dest_char; | ||
340 | |||
341 | switch (src_char) { | ||
342 | case ':': | ||
343 | dest_char = cpu_to_le16(UNI_COLON); | ||
344 | break; | ||
345 | case '*': | ||
346 | dest_char = cpu_to_le16(UNI_ASTERISK); | ||
347 | break; | ||
348 | case '?': | ||
349 | dest_char = cpu_to_le16(UNI_QUESTION); | ||
350 | break; | ||
351 | case '<': | ||
352 | dest_char = cpu_to_le16(UNI_LESSTHAN); | ||
353 | break; | ||
354 | case '>': | ||
355 | dest_char = cpu_to_le16(UNI_GRTRTHAN); | ||
356 | break; | ||
357 | case '|': | ||
358 | dest_char = cpu_to_le16(UNI_PIPE); | ||
359 | break; | ||
360 | default: | ||
361 | dest_char = 0; | ||
362 | } | ||
363 | |||
364 | return dest_char; | ||
365 | } | ||
366 | |||
367 | static __le16 convert_to_sfm_char(char src_char) | ||
368 | { | ||
369 | __le16 dest_char; | ||
370 | |||
371 | switch (src_char) { | ||
372 | case ':': | ||
373 | dest_char = cpu_to_le16(SFM_COLON); | ||
374 | break; | ||
375 | case '*': | ||
376 | dest_char = cpu_to_le16(SFM_ASTERISK); | ||
377 | break; | ||
378 | case '?': | ||
379 | dest_char = cpu_to_le16(SFM_QUESTION); | ||
380 | break; | ||
381 | case '<': | ||
382 | dest_char = cpu_to_le16(SFM_LESSTHAN); | ||
383 | break; | ||
384 | case '>': | ||
385 | dest_char = cpu_to_le16(SFM_GRTRTHAN); | ||
386 | break; | ||
387 | case '|': | ||
388 | dest_char = cpu_to_le16(SFM_PIPE); | ||
389 | break; | ||
390 | default: | ||
391 | dest_char = 0; | ||
392 | } | ||
393 | |||
394 | return dest_char; | ||
395 | } | ||
396 | |||
283 | /* | 397 | /* |
284 | * Convert 16 bit Unicode pathname to wire format from string in current code | 398 | * Convert 16 bit Unicode pathname to wire format from string in current code |
285 | * page. Conversion may involve remapping up the six characters that are | 399 | * page. Conversion may involve remapping up the six characters that are |
@@ -288,7 +402,7 @@ cifs_strndup_from_utf16(const char *src, const int maxlen, | |||
288 | */ | 402 | */ |
289 | int | 403 | int |
290 | cifsConvertToUTF16(__le16 *target, const char *source, int srclen, | 404 | cifsConvertToUTF16(__le16 *target, const char *source, int srclen, |
291 | const struct nls_table *cp, int mapChars) | 405 | const struct nls_table *cp, int map_chars) |
292 | { | 406 | { |
293 | int i, charlen; | 407 | int i, charlen; |
294 | int j = 0; | 408 | int j = 0; |
@@ -296,39 +410,30 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen, | |||
296 | __le16 dst_char; | 410 | __le16 dst_char; |
297 | wchar_t tmp; | 411 | wchar_t tmp; |
298 | 412 | ||
299 | if (!mapChars) | 413 | if (map_chars == NO_MAP_UNI_RSVD) |
300 | return cifs_strtoUTF16(target, source, PATH_MAX, cp); | 414 | return cifs_strtoUTF16(target, source, PATH_MAX, cp); |
301 | 415 | ||
302 | for (i = 0; i < srclen; j++) { | 416 | for (i = 0; i < srclen; j++) { |
303 | src_char = source[i]; | 417 | src_char = source[i]; |
304 | charlen = 1; | 418 | charlen = 1; |
305 | switch (src_char) { | 419 | |
306 | case 0: | 420 | /* check if end of string */ |
421 | if (src_char == 0) | ||
307 | goto ctoUTF16_out; | 422 | goto ctoUTF16_out; |
308 | case ':': | 423 | |
309 | dst_char = cpu_to_le16(UNI_COLON); | 424 | /* see if we must remap this char */ |
310 | break; | 425 | if (map_chars == SFU_MAP_UNI_RSVD) |
311 | case '*': | 426 | dst_char = convert_to_sfu_char(src_char); |
312 | dst_char = cpu_to_le16(UNI_ASTERISK); | 427 | else if (map_chars == SFM_MAP_UNI_RSVD) |
313 | break; | 428 | dst_char = convert_to_sfm_char(src_char); |
314 | case '?': | 429 | else |
315 | dst_char = cpu_to_le16(UNI_QUESTION); | 430 | dst_char = 0; |
316 | break; | ||
317 | case '<': | ||
318 | dst_char = cpu_to_le16(UNI_LESSTHAN); | ||
319 | break; | ||
320 | case '>': | ||
321 | dst_char = cpu_to_le16(UNI_GRTRTHAN); | ||
322 | break; | ||
323 | case '|': | ||
324 | dst_char = cpu_to_le16(UNI_PIPE); | ||
325 | break; | ||
326 | /* | 431 | /* |
327 | * FIXME: We can not handle remapping backslash (UNI_SLASH) | 432 | * FIXME: We can not handle remapping backslash (UNI_SLASH) |
328 | * until all the calls to build_path_from_dentry are modified, | 433 | * until all the calls to build_path_from_dentry are modified, |
329 | * as they use backslash as separator. | 434 | * as they use backslash as separator. |
330 | */ | 435 | */ |
331 | default: | 436 | if (dst_char == 0) { |
332 | charlen = cp->char2uni(source + i, srclen - i, &tmp); | 437 | charlen = cp->char2uni(source + i, srclen - i, &tmp); |
333 | dst_char = cpu_to_le16(tmp); | 438 | dst_char = cpu_to_le16(tmp); |
334 | 439 | ||
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h index d8eac3b6cefb..bdc52cb9a676 100644 --- a/fs/cifs/cifs_unicode.h +++ b/fs/cifs/cifs_unicode.h | |||
@@ -52,6 +52,34 @@ | |||
52 | #define UNI_PIPE (__u16) ('|' + 0xF000) | 52 | #define UNI_PIPE (__u16) ('|' + 0xF000) |
53 | #define UNI_SLASH (__u16) ('\\' + 0xF000) | 53 | #define UNI_SLASH (__u16) ('\\' + 0xF000) |
54 | 54 | ||
55 | /* | ||
56 | * Macs use an older "SFM" mapping of the symbols above. Fortunately it does | ||
57 | * not conflict (although almost does) with the mapping above. | ||
58 | */ | ||
59 | |||
60 | #define SFM_ASTERISK ((__u16) 0xF021) | ||
61 | #define SFM_QUESTION ((__u16) 0xF025) | ||
62 | #define SFM_COLON ((__u16) 0xF022) | ||
63 | #define SFM_GRTRTHAN ((__u16) 0xF024) | ||
64 | #define SFM_LESSTHAN ((__u16) 0xF023) | ||
65 | #define SFM_PIPE ((__u16) 0xF027) | ||
66 | #define SFM_SLASH ((__u16) 0xF026) | ||
67 | |||
68 | /* | ||
69 | * Mapping mechanism to use when one of the seven reserved characters is | ||
70 | * encountered. We can only map using one of the mechanisms at a time | ||
71 | * since otherwise readdir could return directory entries which we would | ||
72 | * not be able to open | ||
73 | * | ||
74 | * NO_MAP_UNI_RSVD = do not perform any remapping of the character | ||
75 | * SFM_MAP_UNI_RSVD = map reserved characters using SFM scheme (MAC compatible) | ||
76 | * SFU_MAP_UNI_RSVD = map reserved characters ala SFU ("mapchars" option) | ||
77 | * | ||
78 | */ | ||
79 | #define NO_MAP_UNI_RSVD 0 | ||
80 | #define SFM_MAP_UNI_RSVD 1 | ||
81 | #define SFU_MAP_UNI_RSVD 2 | ||
82 | |||
55 | /* Just define what we want from uniupr.h. We don't want to define the tables | 83 | /* Just define what we want from uniupr.h. We don't want to define the tables |
56 | * in each source file. | 84 | * in each source file. |
57 | */ | 85 | */ |
@@ -75,7 +103,7 @@ extern const struct UniCaseRange CifsUniLowerRange[]; | |||
75 | 103 | ||
76 | #ifdef __KERNEL__ | 104 | #ifdef __KERNEL__ |
77 | int cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen, | 105 | int cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen, |
78 | const struct nls_table *codepage, bool mapchar); | 106 | const struct nls_table *cp, int map_type); |
79 | int cifs_utf16_bytes(const __le16 *from, int maxbytes, | 107 | int cifs_utf16_bytes(const __le16 *from, int maxbytes, |
80 | const struct nls_table *codepage); | 108 | const struct nls_table *codepage); |
81 | int cifs_strtoUTF16(__le16 *, const char *, int, const struct nls_table *); | 109 | int cifs_strtoUTF16(__le16 *, const char *, int, const struct nls_table *); |
@@ -84,6 +112,7 @@ char *cifs_strndup_from_utf16(const char *src, const int maxlen, | |||
84 | const struct nls_table *codepage); | 112 | const struct nls_table *codepage); |
85 | extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen, | 113 | extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen, |
86 | const struct nls_table *cp, int mapChars); | 114 | const struct nls_table *cp, int mapChars); |
115 | extern int cifs_remap(struct cifs_sb_info *cifs_sb); | ||
87 | #ifdef CONFIG_CIFS_SMB2 | 116 | #ifdef CONFIG_CIFS_SMB2 |
88 | extern __le16 *cifs_strndup_to_utf16(const char *src, const int maxlen, | 117 | extern __le16 *cifs_strndup_to_utf16(const char *src, const int maxlen, |
89 | int *utf16_len, const struct nls_table *cp, | 118 | int *utf16_len, const struct nls_table *cp, |
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 4934347321d3..4ac7445e6ec7 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c | |||
@@ -431,7 +431,7 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp) | |||
431 | return -ENOMEM; | 431 | return -ENOMEM; |
432 | cifs_from_utf16(ses->domainName, | 432 | cifs_from_utf16(ses->domainName, |
433 | (__le16 *)blobptr, attrsize, attrsize, | 433 | (__le16 *)blobptr, attrsize, attrsize, |
434 | nls_cp, false); | 434 | nls_cp, NO_MAP_UNI_RSVD); |
435 | break; | 435 | break; |
436 | } | 436 | } |
437 | } | 437 | } |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 25b8392bfdd2..02a33e529904 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -323,11 +323,11 @@ struct smb_version_operations { | |||
323 | int (*async_writev)(struct cifs_writedata *, | 323 | int (*async_writev)(struct cifs_writedata *, |
324 | void (*release)(struct kref *)); | 324 | void (*release)(struct kref *)); |
325 | /* sync read from the server */ | 325 | /* sync read from the server */ |
326 | int (*sync_read)(const unsigned int, struct cifsFileInfo *, | 326 | int (*sync_read)(const unsigned int, struct cifs_fid *, |
327 | struct cifs_io_parms *, unsigned int *, char **, | 327 | struct cifs_io_parms *, unsigned int *, char **, |
328 | int *); | 328 | int *); |
329 | /* sync write to the server */ | 329 | /* sync write to the server */ |
330 | int (*sync_write)(const unsigned int, struct cifsFileInfo *, | 330 | int (*sync_write)(const unsigned int, struct cifs_fid *, |
331 | struct cifs_io_parms *, unsigned int *, struct kvec *, | 331 | struct cifs_io_parms *, unsigned int *, struct kvec *, |
332 | unsigned long); | 332 | unsigned long); |
333 | /* open dir, start readdir */ | 333 | /* open dir, start readdir */ |
@@ -466,6 +466,7 @@ struct smb_vol { | |||
466 | bool direct_io:1; | 466 | bool direct_io:1; |
467 | bool strict_io:1; /* strict cache behavior */ | 467 | bool strict_io:1; /* strict cache behavior */ |
468 | bool remap:1; /* set to remap seven reserved chars in filenames */ | 468 | bool remap:1; /* set to remap seven reserved chars in filenames */ |
469 | bool sfu_remap:1; /* remap seven reserved chars ala SFU */ | ||
469 | bool posix_paths:1; /* unset to not ask for posix pathnames. */ | 470 | bool posix_paths:1; /* unset to not ask for posix pathnames. */ |
470 | bool no_linux_ext:1; | 471 | bool no_linux_ext:1; |
471 | bool sfu_emul:1; | 472 | bool sfu_emul:1; |
@@ -499,6 +500,7 @@ struct smb_vol { | |||
499 | #define CIFS_MOUNT_MASK (CIFS_MOUNT_NO_PERM | CIFS_MOUNT_SET_UID | \ | 500 | #define CIFS_MOUNT_MASK (CIFS_MOUNT_NO_PERM | CIFS_MOUNT_SET_UID | \ |
500 | CIFS_MOUNT_SERVER_INUM | CIFS_MOUNT_DIRECT_IO | \ | 501 | CIFS_MOUNT_SERVER_INUM | CIFS_MOUNT_DIRECT_IO | \ |
501 | CIFS_MOUNT_NO_XATTR | CIFS_MOUNT_MAP_SPECIAL_CHR | \ | 502 | CIFS_MOUNT_NO_XATTR | CIFS_MOUNT_MAP_SPECIAL_CHR | \ |
503 | CIFS_MOUNT_MAP_SFM_CHR | \ | ||
502 | CIFS_MOUNT_UNX_EMUL | CIFS_MOUNT_NO_BRL | \ | 504 | CIFS_MOUNT_UNX_EMUL | CIFS_MOUNT_NO_BRL | \ |
503 | CIFS_MOUNT_CIFS_ACL | CIFS_MOUNT_OVERR_UID | \ | 505 | CIFS_MOUNT_CIFS_ACL | CIFS_MOUNT_OVERR_UID | \ |
504 | CIFS_MOUNT_OVERR_GID | CIFS_MOUNT_DYNPERM | \ | 506 | CIFS_MOUNT_OVERR_GID | CIFS_MOUNT_DYNPERM | \ |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 66f65001a6d8..61d00a6e398f 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -867,7 +867,7 @@ CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name, | |||
867 | int rc = 0; | 867 | int rc = 0; |
868 | int bytes_returned; | 868 | int bytes_returned; |
869 | int name_len; | 869 | int name_len; |
870 | int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | 870 | int remap = cifs_remap(cifs_sb); |
871 | 871 | ||
872 | DelFileRetry: | 872 | DelFileRetry: |
873 | rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB, | 873 | rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB, |
@@ -913,7 +913,7 @@ CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, | |||
913 | int rc = 0; | 913 | int rc = 0; |
914 | int bytes_returned; | 914 | int bytes_returned; |
915 | int name_len; | 915 | int name_len; |
916 | int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | 916 | int remap = cifs_remap(cifs_sb); |
917 | 917 | ||
918 | cifs_dbg(FYI, "In CIFSSMBRmDir\n"); | 918 | cifs_dbg(FYI, "In CIFSSMBRmDir\n"); |
919 | RmDirRetry: | 919 | RmDirRetry: |
@@ -958,7 +958,7 @@ CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, | |||
958 | CREATE_DIRECTORY_RSP *pSMBr = NULL; | 958 | CREATE_DIRECTORY_RSP *pSMBr = NULL; |
959 | int bytes_returned; | 959 | int bytes_returned; |
960 | int name_len; | 960 | int name_len; |
961 | int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | 961 | int remap = cifs_remap(cifs_sb); |
962 | 962 | ||
963 | cifs_dbg(FYI, "In CIFSSMBMkDir\n"); | 963 | cifs_dbg(FYI, "In CIFSSMBMkDir\n"); |
964 | MkDirRetry: | 964 | MkDirRetry: |
@@ -1280,7 +1280,7 @@ CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock, | |||
1280 | __u16 count; | 1280 | __u16 count; |
1281 | struct cifs_sb_info *cifs_sb = oparms->cifs_sb; | 1281 | struct cifs_sb_info *cifs_sb = oparms->cifs_sb; |
1282 | struct cifs_tcon *tcon = oparms->tcon; | 1282 | struct cifs_tcon *tcon = oparms->tcon; |
1283 | int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | 1283 | int remap = cifs_remap(cifs_sb); |
1284 | const struct nls_table *nls = cifs_sb->local_nls; | 1284 | const struct nls_table *nls = cifs_sb->local_nls; |
1285 | int create_options = oparms->create_options; | 1285 | int create_options = oparms->create_options; |
1286 | int desired_access = oparms->desired_access; | 1286 | int desired_access = oparms->desired_access; |
@@ -2572,7 +2572,7 @@ CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon, | |||
2572 | int bytes_returned; | 2572 | int bytes_returned; |
2573 | int name_len, name_len2; | 2573 | int name_len, name_len2; |
2574 | __u16 count; | 2574 | __u16 count; |
2575 | int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | 2575 | int remap = cifs_remap(cifs_sb); |
2576 | 2576 | ||
2577 | cifs_dbg(FYI, "In CIFSSMBRename\n"); | 2577 | cifs_dbg(FYI, "In CIFSSMBRename\n"); |
2578 | renameRetry: | 2578 | renameRetry: |
@@ -2968,7 +2968,7 @@ CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon, | |||
2968 | int bytes_returned; | 2968 | int bytes_returned; |
2969 | int name_len, name_len2; | 2969 | int name_len, name_len2; |
2970 | __u16 count; | 2970 | __u16 count; |
2971 | int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | 2971 | int remap = cifs_remap(cifs_sb); |
2972 | 2972 | ||
2973 | cifs_dbg(FYI, "In CIFSCreateHardLink\n"); | 2973 | cifs_dbg(FYI, "In CIFSCreateHardLink\n"); |
2974 | winCreateHardLinkRetry: | 2974 | winCreateHardLinkRetry: |
@@ -4367,7 +4367,7 @@ findFirstRetry: | |||
4367 | return rc; | 4367 | return rc; |
4368 | 4368 | ||
4369 | nls_codepage = cifs_sb->local_nls; | 4369 | nls_codepage = cifs_sb->local_nls; |
4370 | remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | 4370 | remap = cifs_remap(cifs_sb); |
4371 | 4371 | ||
4372 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 4372 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
4373 | name_len = | 4373 | name_len = |
@@ -5527,7 +5527,7 @@ CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon, | |||
5527 | int name_len; | 5527 | int name_len; |
5528 | int rc = 0; | 5528 | int rc = 0; |
5529 | int bytes_returned = 0; | 5529 | int bytes_returned = 0; |
5530 | int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | 5530 | int remap = cifs_remap(cifs_sb); |
5531 | 5531 | ||
5532 | __u16 params, byte_count, data_count, param_offset, offset; | 5532 | __u16 params, byte_count, data_count, param_offset, offset; |
5533 | 5533 | ||
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 239e1fb33000..24fa08d261fb 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -70,6 +70,7 @@ enum { | |||
70 | Opt_forcegid, Opt_noforcegid, | 70 | Opt_forcegid, Opt_noforcegid, |
71 | Opt_noblocksend, Opt_noautotune, | 71 | Opt_noblocksend, Opt_noautotune, |
72 | Opt_hard, Opt_soft, Opt_perm, Opt_noperm, | 72 | Opt_hard, Opt_soft, Opt_perm, Opt_noperm, |
73 | Opt_mapposix, Opt_nomapposix, | ||
73 | Opt_mapchars, Opt_nomapchars, Opt_sfu, | 74 | Opt_mapchars, Opt_nomapchars, Opt_sfu, |
74 | Opt_nosfu, Opt_nodfs, Opt_posixpaths, | 75 | Opt_nosfu, Opt_nodfs, Opt_posixpaths, |
75 | Opt_noposixpaths, Opt_nounix, | 76 | Opt_noposixpaths, Opt_nounix, |
@@ -124,8 +125,10 @@ static const match_table_t cifs_mount_option_tokens = { | |||
124 | { Opt_soft, "soft" }, | 125 | { Opt_soft, "soft" }, |
125 | { Opt_perm, "perm" }, | 126 | { Opt_perm, "perm" }, |
126 | { Opt_noperm, "noperm" }, | 127 | { Opt_noperm, "noperm" }, |
127 | { Opt_mapchars, "mapchars" }, | 128 | { Opt_mapchars, "mapchars" }, /* SFU style */ |
128 | { Opt_nomapchars, "nomapchars" }, | 129 | { Opt_nomapchars, "nomapchars" }, |
130 | { Opt_mapposix, "mapposix" }, /* SFM style */ | ||
131 | { Opt_nomapposix, "nomapposix" }, | ||
129 | { Opt_sfu, "sfu" }, | 132 | { Opt_sfu, "sfu" }, |
130 | { Opt_nosfu, "nosfu" }, | 133 | { Opt_nosfu, "nosfu" }, |
131 | { Opt_nodfs, "nodfs" }, | 134 | { Opt_nodfs, "nodfs" }, |
@@ -1231,6 +1234,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1231 | vol->linux_uid = current_uid(); | 1234 | vol->linux_uid = current_uid(); |
1232 | vol->linux_gid = current_gid(); | 1235 | vol->linux_gid = current_gid(); |
1233 | 1236 | ||
1237 | /* | ||
1238 | * default to SFM style remapping of seven reserved characters | ||
1239 | * unless user overrides it or we negotiate CIFS POSIX where | ||
1240 | * it is unnecessary. Can not simultaneously use more than one mapping | ||
1241 | * since then readdir could list files that open could not open | ||
1242 | */ | ||
1243 | vol->remap = true; | ||
1244 | |||
1234 | /* default to only allowing write access to owner of the mount */ | 1245 | /* default to only allowing write access to owner of the mount */ |
1235 | vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR; | 1246 | vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR; |
1236 | 1247 | ||
@@ -1338,10 +1349,18 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, | |||
1338 | vol->noperm = 1; | 1349 | vol->noperm = 1; |
1339 | break; | 1350 | break; |
1340 | case Opt_mapchars: | 1351 | case Opt_mapchars: |
1341 | vol->remap = 1; | 1352 | vol->sfu_remap = true; |
1353 | vol->remap = false; /* disable SFM mapping */ | ||
1342 | break; | 1354 | break; |
1343 | case Opt_nomapchars: | 1355 | case Opt_nomapchars: |
1344 | vol->remap = 0; | 1356 | vol->sfu_remap = false; |
1357 | break; | ||
1358 | case Opt_mapposix: | ||
1359 | vol->remap = true; | ||
1360 | vol->sfu_remap = false; /* disable SFU mapping */ | ||
1361 | break; | ||
1362 | case Opt_nomapposix: | ||
1363 | vol->remap = false; | ||
1345 | break; | 1364 | break; |
1346 | case Opt_sfu: | 1365 | case Opt_sfu: |
1347 | vol->sfu_emul = 1; | 1366 | vol->sfu_emul = 1; |
@@ -3197,6 +3216,8 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, | |||
3197 | if (pvolume_info->server_ino) | 3216 | if (pvolume_info->server_ino) |
3198 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; | 3217 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; |
3199 | if (pvolume_info->remap) | 3218 | if (pvolume_info->remap) |
3219 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR; | ||
3220 | if (pvolume_info->sfu_remap) | ||
3200 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; | 3221 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; |
3201 | if (pvolume_info->no_xattr) | 3222 | if (pvolume_info->no_xattr) |
3202 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; | 3223 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; |
@@ -3239,10 +3260,20 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, | |||
3239 | } | 3260 | } |
3240 | if (pvolume_info->mfsymlinks) { | 3261 | if (pvolume_info->mfsymlinks) { |
3241 | if (pvolume_info->sfu_emul) { | 3262 | if (pvolume_info->sfu_emul) { |
3242 | cifs_dbg(VFS, "mount option mfsymlinks ignored if sfu mount option is used\n"); | 3263 | /* |
3243 | } else { | 3264 | * Our SFU ("Services for Unix" emulation does not allow |
3244 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS; | 3265 | * creating symlinks but does allow reading existing SFU |
3266 | * symlinks (it does allow both creating and reading SFU | ||
3267 | * style mknod and FIFOs though). When "mfsymlinks" and | ||
3268 | * "sfu" are both enabled at the same time, it allows | ||
3269 | * reading both types of symlinks, but will only create | ||
3270 | * them with mfsymlinks format. This allows better | ||
3271 | * Apple compatibility (probably better for Samba too) | ||
3272 | * while still recognizing old Windows style symlinks. | ||
3273 | */ | ||
3274 | cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n"); | ||
3245 | } | 3275 | } |
3276 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS; | ||
3246 | } | 3277 | } |
3247 | 3278 | ||
3248 | if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm)) | 3279 | if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm)) |
@@ -3330,8 +3361,7 @@ expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses, | |||
3330 | ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1; | 3361 | ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1; |
3331 | 3362 | ||
3332 | rc = get_dfs_path(xid, ses, ref_path, cifs_sb->local_nls, | 3363 | rc = get_dfs_path(xid, ses, ref_path, cifs_sb->local_nls, |
3333 | &num_referrals, &referrals, | 3364 | &num_referrals, &referrals, cifs_remap(cifs_sb)); |
3334 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
3335 | 3365 | ||
3336 | if (!rc && num_referrals > 0) { | 3366 | if (!rc && num_referrals > 0) { |
3337 | char *fake_devname = NULL; | 3367 | char *fake_devname = NULL; |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 073640675a39..b72bc29cba23 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -577,12 +577,13 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
577 | struct cifs_io_parms io_parms; | 577 | struct cifs_io_parms io_parms; |
578 | char *full_path = NULL; | 578 | char *full_path = NULL; |
579 | struct inode *newinode = NULL; | 579 | struct inode *newinode = NULL; |
580 | int oplock = 0; | 580 | __u32 oplock = 0; |
581 | struct cifs_fid fid; | 581 | struct cifs_fid fid; |
582 | struct cifs_open_parms oparms; | 582 | struct cifs_open_parms oparms; |
583 | FILE_ALL_INFO *buf = NULL; | 583 | FILE_ALL_INFO *buf = NULL; |
584 | unsigned int bytes_written; | 584 | unsigned int bytes_written; |
585 | struct win_dev *pdev; | 585 | struct win_dev *pdev; |
586 | struct kvec iov[2]; | ||
586 | 587 | ||
587 | if (!old_valid_dev(device_number)) | 588 | if (!old_valid_dev(device_number)) |
588 | return -EINVAL; | 589 | return -EINVAL; |
@@ -658,7 +659,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
658 | oparms.fid = &fid; | 659 | oparms.fid = &fid; |
659 | oparms.reconnect = false; | 660 | oparms.reconnect = false; |
660 | 661 | ||
661 | rc = CIFS_open(xid, &oparms, &oplock, buf); | 662 | if (tcon->ses->server->oplocks) |
663 | oplock = REQ_OPLOCK; | ||
664 | else | ||
665 | oplock = 0; | ||
666 | rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, buf); | ||
662 | if (rc) | 667 | if (rc) |
663 | goto mknod_out; | 668 | goto mknod_out; |
664 | 669 | ||
@@ -668,25 +673,26 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
668 | */ | 673 | */ |
669 | 674 | ||
670 | pdev = (struct win_dev *)buf; | 675 | pdev = (struct win_dev *)buf; |
671 | io_parms.netfid = fid.netfid; | ||
672 | io_parms.pid = current->tgid; | 676 | io_parms.pid = current->tgid; |
673 | io_parms.tcon = tcon; | 677 | io_parms.tcon = tcon; |
674 | io_parms.offset = 0; | 678 | io_parms.offset = 0; |
675 | io_parms.length = sizeof(struct win_dev); | 679 | io_parms.length = sizeof(struct win_dev); |
680 | iov[1].iov_base = buf; | ||
681 | iov[1].iov_len = sizeof(struct win_dev); | ||
676 | if (S_ISCHR(mode)) { | 682 | if (S_ISCHR(mode)) { |
677 | memcpy(pdev->type, "IntxCHR", 8); | 683 | memcpy(pdev->type, "IntxCHR", 8); |
678 | pdev->major = cpu_to_le64(MAJOR(device_number)); | 684 | pdev->major = cpu_to_le64(MAJOR(device_number)); |
679 | pdev->minor = cpu_to_le64(MINOR(device_number)); | 685 | pdev->minor = cpu_to_le64(MINOR(device_number)); |
680 | rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev, | 686 | rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, |
681 | NULL, 0); | 687 | &bytes_written, iov, 1); |
682 | } else if (S_ISBLK(mode)) { | 688 | } else if (S_ISBLK(mode)) { |
683 | memcpy(pdev->type, "IntxBLK", 8); | 689 | memcpy(pdev->type, "IntxBLK", 8); |
684 | pdev->major = cpu_to_le64(MAJOR(device_number)); | 690 | pdev->major = cpu_to_le64(MAJOR(device_number)); |
685 | pdev->minor = cpu_to_le64(MINOR(device_number)); | 691 | pdev->minor = cpu_to_le64(MINOR(device_number)); |
686 | rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev, | 692 | rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, |
687 | NULL, 0); | 693 | &bytes_written, iov, 1); |
688 | } /* else if (S_ISFIFO) */ | 694 | } /* else if (S_ISFIFO) */ |
689 | CIFSSMBClose(xid, tcon, fid.netfid); | 695 | tcon->ses->server->ops->close(xid, tcon, &fid); |
690 | d_drop(direntry); | 696 | d_drop(direntry); |
691 | 697 | ||
692 | /* FIXME: add code here to set EAs */ | 698 | /* FIXME: add code here to set EAs */ |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 8f7b40fd8f3b..3e4d00a06c44 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1687,8 +1687,8 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data, | |||
1687 | io_parms.tcon = tcon; | 1687 | io_parms.tcon = tcon; |
1688 | io_parms.offset = *offset; | 1688 | io_parms.offset = *offset; |
1689 | io_parms.length = len; | 1689 | io_parms.length = len; |
1690 | rc = server->ops->sync_write(xid, open_file, &io_parms, | 1690 | rc = server->ops->sync_write(xid, &open_file->fid, |
1691 | &bytes_written, iov, 1); | 1691 | &io_parms, &bytes_written, iov, 1); |
1692 | } | 1692 | } |
1693 | if (rc || (bytes_written == 0)) { | 1693 | if (rc || (bytes_written == 0)) { |
1694 | if (total_written) | 1694 | if (total_written) |
@@ -3206,7 +3206,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset) | |||
3206 | io_parms.tcon = tcon; | 3206 | io_parms.tcon = tcon; |
3207 | io_parms.offset = *offset; | 3207 | io_parms.offset = *offset; |
3208 | io_parms.length = current_read_size; | 3208 | io_parms.length = current_read_size; |
3209 | rc = server->ops->sync_read(xid, open_file, &io_parms, | 3209 | rc = server->ops->sync_read(xid, &open_file->fid, &io_parms, |
3210 | &bytes_read, &cur_offset, | 3210 | &bytes_read, &cur_offset, |
3211 | &buf_type); | 3211 | &buf_type); |
3212 | } while (rc == -EAGAIN); | 3212 | } while (rc == -EAGAIN); |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 8fd4ee8e07ff..197cb503d528 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "cifsproto.h" | 30 | #include "cifsproto.h" |
31 | #include "cifs_debug.h" | 31 | #include "cifs_debug.h" |
32 | #include "cifs_fs_sb.h" | 32 | #include "cifs_fs_sb.h" |
33 | #include "cifs_unicode.h" | ||
33 | #include "fscache.h" | 34 | #include "fscache.h" |
34 | 35 | ||
35 | 36 | ||
@@ -412,7 +413,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path, | |||
412 | struct cifs_sb_info *cifs_sb, unsigned int xid) | 413 | struct cifs_sb_info *cifs_sb, unsigned int xid) |
413 | { | 414 | { |
414 | int rc; | 415 | int rc; |
415 | int oplock = 0; | 416 | __u32 oplock; |
416 | struct tcon_link *tlink; | 417 | struct tcon_link *tlink; |
417 | struct cifs_tcon *tcon; | 418 | struct cifs_tcon *tcon; |
418 | struct cifs_fid fid; | 419 | struct cifs_fid fid; |
@@ -451,8 +452,13 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path, | |||
451 | oparms.fid = &fid; | 452 | oparms.fid = &fid; |
452 | oparms.reconnect = false; | 453 | oparms.reconnect = false; |
453 | 454 | ||
454 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | 455 | if (tcon->ses->server->oplocks) |
456 | oplock = REQ_OPLOCK; | ||
457 | else | ||
458 | oplock = 0; | ||
459 | rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL); | ||
455 | if (rc) { | 460 | if (rc) { |
461 | cifs_dbg(FYI, "check sfu type of %s, open rc = %d\n", path, rc); | ||
456 | cifs_put_tlink(tlink); | 462 | cifs_put_tlink(tlink); |
457 | return rc; | 463 | return rc; |
458 | } | 464 | } |
@@ -464,7 +470,8 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path, | |||
464 | io_parms.offset = 0; | 470 | io_parms.offset = 0; |
465 | io_parms.length = 24; | 471 | io_parms.length = 24; |
466 | 472 | ||
467 | rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type); | 473 | rc = tcon->ses->server->ops->sync_read(xid, &fid, &io_parms, |
474 | &bytes_read, &pbuf, &buf_type); | ||
468 | if ((rc == 0) && (bytes_read >= 8)) { | 475 | if ((rc == 0) && (bytes_read >= 8)) { |
469 | if (memcmp("IntxBLK", pbuf, 8) == 0) { | 476 | if (memcmp("IntxBLK", pbuf, 8) == 0) { |
470 | cifs_dbg(FYI, "Block device\n"); | 477 | cifs_dbg(FYI, "Block device\n"); |
@@ -504,7 +511,8 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path, | |||
504 | fattr->cf_dtype = DT_REG; | 511 | fattr->cf_dtype = DT_REG; |
505 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ | 512 | rc = -EOPNOTSUPP; /* or some unknown SFU type */ |
506 | } | 513 | } |
507 | CIFSSMBClose(xid, tcon, fid.netfid); | 514 | |
515 | tcon->ses->server->ops->close(xid, tcon, &fid); | ||
508 | cifs_put_tlink(tlink); | 516 | cifs_put_tlink(tlink); |
509 | return rc; | 517 | return rc; |
510 | } | 518 | } |
@@ -539,7 +547,7 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, | |||
539 | rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path, | 547 | rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path, |
540 | "SETFILEBITS", ea_value, 4 /* size of buf */, | 548 | "SETFILEBITS", ea_value, 4 /* size of buf */, |
541 | cifs_sb->local_nls, | 549 | cifs_sb->local_nls, |
542 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 550 | cifs_remap(cifs_sb)); |
543 | cifs_put_tlink(tlink); | 551 | cifs_put_tlink(tlink); |
544 | if (rc < 0) | 552 | if (rc < 0) |
545 | return (int)rc; | 553 | return (int)rc; |
@@ -952,11 +960,18 @@ struct inode *cifs_root_iget(struct super_block *sb) | |||
952 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); | 960 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); |
953 | 961 | ||
954 | xid = get_xid(); | 962 | xid = get_xid(); |
955 | if (tcon->unix_ext) | 963 | if (tcon->unix_ext) { |
956 | rc = cifs_get_inode_info_unix(&inode, "", sb, xid); | 964 | rc = cifs_get_inode_info_unix(&inode, "", sb, xid); |
957 | else | 965 | /* some servers mistakenly claim POSIX support */ |
958 | rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL); | 966 | if (rc != -EOPNOTSUPP) |
967 | goto iget_no_retry; | ||
968 | cifs_dbg(VFS, "server does not support POSIX extensions"); | ||
969 | tcon->unix_ext = false; | ||
970 | } | ||
971 | |||
972 | rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL); | ||
959 | 973 | ||
974 | iget_no_retry: | ||
960 | if (!inode) { | 975 | if (!inode) { |
961 | inode = ERR_PTR(rc); | 976 | inode = ERR_PTR(rc); |
962 | goto out; | 977 | goto out; |
@@ -1117,8 +1132,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry, | |||
1117 | /* rename the file */ | 1132 | /* rename the file */ |
1118 | rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL, | 1133 | rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL, |
1119 | cifs_sb->local_nls, | 1134 | cifs_sb->local_nls, |
1120 | cifs_sb->mnt_cifs_flags & | 1135 | cifs_remap(cifs_sb)); |
1121 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1122 | if (rc != 0) { | 1136 | if (rc != 0) { |
1123 | rc = -EBUSY; | 1137 | rc = -EBUSY; |
1124 | goto undo_setattr; | 1138 | goto undo_setattr; |
@@ -1159,8 +1173,7 @@ out: | |||
1159 | */ | 1173 | */ |
1160 | undo_rename: | 1174 | undo_rename: |
1161 | CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name, | 1175 | CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name, |
1162 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 1176 | cifs_sb->local_nls, cifs_remap(cifs_sb)); |
1163 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1164 | undo_setattr: | 1177 | undo_setattr: |
1165 | if (dosattr != origattr) { | 1178 | if (dosattr != origattr) { |
1166 | info_buf->Attributes = cpu_to_le32(origattr); | 1179 | info_buf->Attributes = cpu_to_le32(origattr); |
@@ -1226,7 +1239,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) | |||
1226 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | 1239 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
1227 | rc = CIFSPOSIXDelFile(xid, tcon, full_path, | 1240 | rc = CIFSPOSIXDelFile(xid, tcon, full_path, |
1228 | SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls, | 1241 | SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls, |
1229 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 1242 | cifs_remap(cifs_sb)); |
1230 | cifs_dbg(FYI, "posix del rc %d\n", rc); | 1243 | cifs_dbg(FYI, "posix del rc %d\n", rc); |
1231 | if ((rc == 0) || (rc == -ENOENT)) | 1244 | if ((rc == 0) || (rc == -ENOENT)) |
1232 | goto psx_del_no_retry; | 1245 | goto psx_del_no_retry; |
@@ -1349,8 +1362,7 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode, | |||
1349 | } | 1362 | } |
1350 | CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, | 1363 | CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, |
1351 | cifs_sb->local_nls, | 1364 | cifs_sb->local_nls, |
1352 | cifs_sb->mnt_cifs_flags & | 1365 | cifs_remap(cifs_sb)); |
1353 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1354 | } else { | 1366 | } else { |
1355 | struct TCP_Server_Info *server = tcon->ses->server; | 1367 | struct TCP_Server_Info *server = tcon->ses->server; |
1356 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && | 1368 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) && |
@@ -1392,8 +1404,7 @@ cifs_posix_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode, | |||
1392 | mode &= ~current_umask(); | 1404 | mode &= ~current_umask(); |
1393 | rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode, | 1405 | rc = CIFSPOSIXCreate(xid, tcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode, |
1394 | NULL /* netfid */, info, &oplock, full_path, | 1406 | NULL /* netfid */, info, &oplock, full_path, |
1395 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 1407 | cifs_sb->local_nls, cifs_remap(cifs_sb)); |
1396 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1397 | if (rc == -EOPNOTSUPP) | 1408 | if (rc == -EOPNOTSUPP) |
1398 | goto posix_mkdir_out; | 1409 | goto posix_mkdir_out; |
1399 | else if (rc) { | 1410 | else if (rc) { |
@@ -1617,8 +1628,7 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, | |||
1617 | if (rc == 0) { | 1628 | if (rc == 0) { |
1618 | rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, | 1629 | rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, |
1619 | (const char *) to_dentry->d_name.name, | 1630 | (const char *) to_dentry->d_name.name, |
1620 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 1631 | cifs_sb->local_nls, cifs_remap(cifs_sb)); |
1621 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1622 | CIFSSMBClose(xid, tcon, fid.netfid); | 1632 | CIFSSMBClose(xid, tcon, fid.netfid); |
1623 | } | 1633 | } |
1624 | do_rename_exit: | 1634 | do_rename_exit: |
@@ -1694,16 +1704,14 @@ cifs_rename2(struct inode *source_dir, struct dentry *source_dentry, | |||
1694 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name, | 1704 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name, |
1695 | info_buf_source, | 1705 | info_buf_source, |
1696 | cifs_sb->local_nls, | 1706 | cifs_sb->local_nls, |
1697 | cifs_sb->mnt_cifs_flags & | 1707 | cifs_remap(cifs_sb)); |
1698 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1699 | if (tmprc != 0) | 1708 | if (tmprc != 0) |
1700 | goto unlink_target; | 1709 | goto unlink_target; |
1701 | 1710 | ||
1702 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name, | 1711 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name, |
1703 | info_buf_target, | 1712 | info_buf_target, |
1704 | cifs_sb->local_nls, | 1713 | cifs_sb->local_nls, |
1705 | cifs_sb->mnt_cifs_flags & | 1714 | cifs_remap(cifs_sb)); |
1706 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1707 | 1715 | ||
1708 | if (tmprc == 0 && (info_buf_source->UniqueId == | 1716 | if (tmprc == 0 && (info_buf_source->UniqueId == |
1709 | info_buf_target->UniqueId)) { | 1717 | info_buf_target->UniqueId)) { |
@@ -2068,8 +2076,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
2068 | rc = SMBLegacyOpen(xid, tcon, full_path, FILE_OPEN, | 2076 | rc = SMBLegacyOpen(xid, tcon, full_path, FILE_OPEN, |
2069 | GENERIC_WRITE, CREATE_NOT_DIR, &netfid, | 2077 | GENERIC_WRITE, CREATE_NOT_DIR, &netfid, |
2070 | &oplock, NULL, cifs_sb->local_nls, | 2078 | &oplock, NULL, cifs_sb->local_nls, |
2071 | cifs_sb->mnt_cifs_flags & | 2079 | cifs_remap(cifs_sb)); |
2072 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
2073 | if (rc == 0) { | 2080 | if (rc == 0) { |
2074 | unsigned int bytes_written; | 2081 | unsigned int bytes_written; |
2075 | 2082 | ||
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 5657416d3483..2ec6037f61c7 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
@@ -28,6 +28,10 @@ | |||
28 | #include "cifsproto.h" | 28 | #include "cifsproto.h" |
29 | #include "cifs_debug.h" | 29 | #include "cifs_debug.h" |
30 | #include "cifs_fs_sb.h" | 30 | #include "cifs_fs_sb.h" |
31 | #include "cifs_unicode.h" | ||
32 | #ifdef CONFIG_CIFS_SMB2 | ||
33 | #include "smb2proto.h" | ||
34 | #endif | ||
31 | 35 | ||
32 | /* | 36 | /* |
33 | * M-F Symlink Functions - Begin | 37 | * M-F Symlink Functions - Begin |
@@ -401,6 +405,134 @@ cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, | |||
401 | } | 405 | } |
402 | 406 | ||
403 | /* | 407 | /* |
408 | * SMB 2.1/SMB3 Protocol specific functions | ||
409 | */ | ||
410 | #ifdef CONFIG_CIFS_SMB2 | ||
411 | int | ||
412 | smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, | ||
413 | struct cifs_sb_info *cifs_sb, const unsigned char *path, | ||
414 | char *pbuf, unsigned int *pbytes_read) | ||
415 | { | ||
416 | int rc; | ||
417 | struct cifs_fid fid; | ||
418 | struct cifs_open_parms oparms; | ||
419 | struct cifs_io_parms io_parms; | ||
420 | int buf_type = CIFS_NO_BUFFER; | ||
421 | __le16 *utf16_path; | ||
422 | __u8 oplock = SMB2_OPLOCK_LEVEL_II; | ||
423 | struct smb2_file_all_info *pfile_info = NULL; | ||
424 | |||
425 | oparms.tcon = tcon; | ||
426 | oparms.cifs_sb = cifs_sb; | ||
427 | oparms.desired_access = GENERIC_READ; | ||
428 | oparms.create_options = CREATE_NOT_DIR; | ||
429 | if (backup_cred(cifs_sb)) | ||
430 | oparms.create_options |= CREATE_OPEN_BACKUP_INTENT; | ||
431 | oparms.disposition = FILE_OPEN; | ||
432 | oparms.fid = &fid; | ||
433 | oparms.reconnect = false; | ||
434 | |||
435 | utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); | ||
436 | if (utf16_path == NULL) | ||
437 | return -ENOMEM; | ||
438 | |||
439 | pfile_info = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2, | ||
440 | GFP_KERNEL); | ||
441 | |||
442 | if (pfile_info == NULL) { | ||
443 | kfree(utf16_path); | ||
444 | return -ENOMEM; | ||
445 | } | ||
446 | |||
447 | rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL); | ||
448 | if (rc) | ||
449 | goto qmf_out_open_fail; | ||
450 | |||
451 | if (pfile_info->EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { | ||
452 | /* it's not a symlink */ | ||
453 | rc = -ENOENT; /* Is there a better rc to return? */ | ||
454 | goto qmf_out; | ||
455 | } | ||
456 | |||
457 | io_parms.netfid = fid.netfid; | ||
458 | io_parms.pid = current->tgid; | ||
459 | io_parms.tcon = tcon; | ||
460 | io_parms.offset = 0; | ||
461 | io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; | ||
462 | io_parms.persistent_fid = fid.persistent_fid; | ||
463 | io_parms.volatile_fid = fid.volatile_fid; | ||
464 | rc = SMB2_read(xid, &io_parms, pbytes_read, &pbuf, &buf_type); | ||
465 | qmf_out: | ||
466 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); | ||
467 | qmf_out_open_fail: | ||
468 | kfree(utf16_path); | ||
469 | kfree(pfile_info); | ||
470 | return rc; | ||
471 | } | ||
472 | |||
473 | int | ||
474 | smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, | ||
475 | struct cifs_sb_info *cifs_sb, const unsigned char *path, | ||
476 | char *pbuf, unsigned int *pbytes_written) | ||
477 | { | ||
478 | int rc; | ||
479 | struct cifs_fid fid; | ||
480 | struct cifs_open_parms oparms; | ||
481 | struct cifs_io_parms io_parms; | ||
482 | int create_options = CREATE_NOT_DIR; | ||
483 | __le16 *utf16_path; | ||
484 | __u8 oplock = SMB2_OPLOCK_LEVEL_EXCLUSIVE; | ||
485 | struct kvec iov[2]; | ||
486 | |||
487 | if (backup_cred(cifs_sb)) | ||
488 | create_options |= CREATE_OPEN_BACKUP_INTENT; | ||
489 | |||
490 | cifs_dbg(FYI, "%s: path: %s\n", __func__, path); | ||
491 | |||
492 | utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); | ||
493 | if (!utf16_path) | ||
494 | return -ENOMEM; | ||
495 | |||
496 | oparms.tcon = tcon; | ||
497 | oparms.cifs_sb = cifs_sb; | ||
498 | oparms.desired_access = GENERIC_WRITE; | ||
499 | oparms.create_options = create_options; | ||
500 | oparms.disposition = FILE_CREATE; | ||
501 | oparms.fid = &fid; | ||
502 | oparms.reconnect = false; | ||
503 | |||
504 | rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL); | ||
505 | if (rc) { | ||
506 | kfree(utf16_path); | ||
507 | return rc; | ||
508 | } | ||
509 | |||
510 | io_parms.netfid = fid.netfid; | ||
511 | io_parms.pid = current->tgid; | ||
512 | io_parms.tcon = tcon; | ||
513 | io_parms.offset = 0; | ||
514 | io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; | ||
515 | io_parms.persistent_fid = fid.persistent_fid; | ||
516 | io_parms.volatile_fid = fid.volatile_fid; | ||
517 | |||
518 | /* iov[0] is reserved for smb header */ | ||
519 | iov[1].iov_base = pbuf; | ||
520 | iov[1].iov_len = CIFS_MF_SYMLINK_FILE_SIZE; | ||
521 | |||
522 | rc = SMB2_write(xid, &io_parms, pbytes_written, iov, 1); | ||
523 | |||
524 | /* Make sure we wrote all of the symlink data */ | ||
525 | if ((rc == 0) && (*pbytes_written != CIFS_MF_SYMLINK_FILE_SIZE)) | ||
526 | rc = -EIO; | ||
527 | |||
528 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); | ||
529 | |||
530 | kfree(utf16_path); | ||
531 | return rc; | ||
532 | } | ||
533 | #endif /* CONFIG_CIFS_SMB2 */ | ||
534 | |||
535 | /* | ||
404 | * M-F Symlink Functions - End | 536 | * M-F Symlink Functions - End |
405 | */ | 537 | */ |
406 | 538 | ||
@@ -435,8 +567,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, | |||
435 | if (tcon->unix_ext) | 567 | if (tcon->unix_ext) |
436 | rc = CIFSUnixCreateHardLink(xid, tcon, from_name, to_name, | 568 | rc = CIFSUnixCreateHardLink(xid, tcon, from_name, to_name, |
437 | cifs_sb->local_nls, | 569 | cifs_sb->local_nls, |
438 | cifs_sb->mnt_cifs_flags & | 570 | cifs_remap(cifs_sb)); |
439 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
440 | else { | 571 | else { |
441 | server = tcon->ses->server; | 572 | server = tcon->ses->server; |
442 | if (!server->ops->create_hardlink) { | 573 | if (!server->ops->create_hardlink) { |
@@ -461,11 +592,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, | |||
461 | spin_lock(&old_file->d_inode->i_lock); | 592 | spin_lock(&old_file->d_inode->i_lock); |
462 | inc_nlink(old_file->d_inode); | 593 | inc_nlink(old_file->d_inode); |
463 | spin_unlock(&old_file->d_inode->i_lock); | 594 | spin_unlock(&old_file->d_inode->i_lock); |
464 | /* | 595 | |
465 | * BB should we make this contingent on superblock flag | ||
466 | * NOATIME? | ||
467 | */ | ||
468 | /* old_file->d_inode->i_ctime = CURRENT_TIME; */ | ||
469 | /* | 596 | /* |
470 | * parent dir timestamps will update from srv within a | 597 | * parent dir timestamps will update from srv within a |
471 | * second, would it really be worth it to set the parent | 598 | * second, would it really be worth it to set the parent |
@@ -475,7 +602,9 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, | |||
475 | } | 602 | } |
476 | /* | 603 | /* |
477 | * if not oplocked will force revalidate to get info on source | 604 | * if not oplocked will force revalidate to get info on source |
478 | * file from srv | 605 | * file from srv. Note Samba server prior to 4.2 has bug - |
606 | * not updating src file ctime on hardlinks but Windows servers | ||
607 | * handle it properly | ||
479 | */ | 608 | */ |
480 | cifsInode->time = 0; | 609 | cifsInode->time = 0; |
481 | 610 | ||
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index d2141f101382..8fd2a95860ba 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -239,7 +239,7 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb, | |||
239 | rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ, | 239 | rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ, |
240 | OPEN_REPARSE_POINT, &fid, &oplock, NULL, | 240 | OPEN_REPARSE_POINT, &fid, &oplock, NULL, |
241 | cifs_sb->local_nls, | 241 | cifs_sb->local_nls, |
242 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 242 | cifs_remap(cifs_sb); |
243 | if (!rc) { | 243 | if (!rc) { |
244 | tmpbuffer = kmalloc(maxpath); | 244 | tmpbuffer = kmalloc(maxpath); |
245 | rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path, | 245 | rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path, |
@@ -704,15 +704,15 @@ static int cifs_filldir(char *find_entry, struct file *file, | |||
704 | 704 | ||
705 | if (file_info->srch_inf.unicode) { | 705 | if (file_info->srch_inf.unicode) { |
706 | struct nls_table *nlt = cifs_sb->local_nls; | 706 | struct nls_table *nlt = cifs_sb->local_nls; |
707 | int map_type; | ||
707 | 708 | ||
709 | map_type = cifs_remap(cifs_sb); | ||
708 | name.name = scratch_buf; | 710 | name.name = scratch_buf; |
709 | name.len = | 711 | name.len = |
710 | cifs_from_utf16((char *)name.name, (__le16 *)de.name, | 712 | cifs_from_utf16((char *)name.name, (__le16 *)de.name, |
711 | UNICODE_NAME_MAX, | 713 | UNICODE_NAME_MAX, |
712 | min_t(size_t, de.namelen, | 714 | min_t(size_t, de.namelen, |
713 | (size_t)max_len), nlt, | 715 | (size_t)max_len), nlt, map_type); |
714 | cifs_sb->mnt_cifs_flags & | ||
715 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
716 | name.len -= nls_nullsize(nlt); | 716 | name.len -= nls_nullsize(nlt); |
717 | } else { | 717 | } else { |
718 | name.name = de.name; | 718 | name.name = de.name; |
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 52131d8cb4d5..d2979036a4c7 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include "cifsproto.h" | 23 | #include "cifsproto.h" |
24 | #include "cifs_debug.h" | 24 | #include "cifs_debug.h" |
25 | #include "cifspdu.h" | 25 | #include "cifspdu.h" |
26 | #include "cifs_unicode.h" | ||
26 | 27 | ||
27 | /* | 28 | /* |
28 | * An NT cancel request header looks just like the original request except: | 29 | * An NT cancel request header looks just like the original request except: |
@@ -530,13 +531,11 @@ cifs_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, | |||
530 | 531 | ||
531 | rc = CIFSSMBQPathInfo(xid, tcon, full_path, file_info, | 532 | rc = CIFSSMBQPathInfo(xid, tcon, full_path, file_info, |
532 | 0 /* not legacy */, cifs_sb->local_nls, | 533 | 0 /* not legacy */, cifs_sb->local_nls, |
533 | cifs_sb->mnt_cifs_flags & | 534 | cifs_remap(cifs_sb)); |
534 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
535 | 535 | ||
536 | if (rc == -EOPNOTSUPP || rc == -EINVAL) | 536 | if (rc == -EOPNOTSUPP || rc == -EINVAL) |
537 | rc = SMBQueryInformation(xid, tcon, full_path, file_info, | 537 | rc = SMBQueryInformation(xid, tcon, full_path, file_info, |
538 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 538 | cifs_sb->local_nls, cifs_remap(cifs_sb)); |
539 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
540 | kfree(file_info); | 539 | kfree(file_info); |
541 | return rc; | 540 | return rc; |
542 | } | 541 | } |
@@ -552,8 +551,7 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
552 | 551 | ||
553 | /* could do find first instead but this returns more info */ | 552 | /* could do find first instead but this returns more info */ |
554 | rc = CIFSSMBQPathInfo(xid, tcon, full_path, data, 0 /* not legacy */, | 553 | rc = CIFSSMBQPathInfo(xid, tcon, full_path, data, 0 /* not legacy */, |
555 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 554 | cifs_sb->local_nls, cifs_remap(cifs_sb)); |
556 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
557 | /* | 555 | /* |
558 | * BB optimize code so we do not make the above call when server claims | 556 | * BB optimize code so we do not make the above call when server claims |
559 | * no NT SMB support and the above call failed at least once - set flag | 557 | * no NT SMB support and the above call failed at least once - set flag |
@@ -562,8 +560,7 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
562 | if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { | 560 | if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { |
563 | rc = SMBQueryInformation(xid, tcon, full_path, data, | 561 | rc = SMBQueryInformation(xid, tcon, full_path, data, |
564 | cifs_sb->local_nls, | 562 | cifs_sb->local_nls, |
565 | cifs_sb->mnt_cifs_flags & | 563 | cifs_remap(cifs_sb)); |
566 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
567 | *adjustTZ = true; | 564 | *adjustTZ = true; |
568 | } | 565 | } |
569 | 566 | ||
@@ -611,8 +608,7 @@ cifs_get_srv_inum(const unsigned int xid, struct cifs_tcon *tcon, | |||
611 | */ | 608 | */ |
612 | return CIFSGetSrvInodeNumber(xid, tcon, full_path, uniqueid, | 609 | return CIFSGetSrvInodeNumber(xid, tcon, full_path, uniqueid, |
613 | cifs_sb->local_nls, | 610 | cifs_sb->local_nls, |
614 | cifs_sb->mnt_cifs_flags & | 611 | cifs_remap(cifs_sb)); |
615 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
616 | } | 612 | } |
617 | 613 | ||
618 | static int | 614 | static int |
@@ -703,8 +699,7 @@ cifs_mkdir_setinfo(struct inode *inode, const char *full_path, | |||
703 | dosattrs = cifsInode->cifsAttrs|ATTR_READONLY; | 699 | dosattrs = cifsInode->cifsAttrs|ATTR_READONLY; |
704 | info.Attributes = cpu_to_le32(dosattrs); | 700 | info.Attributes = cpu_to_le32(dosattrs); |
705 | rc = CIFSSMBSetPathInfo(xid, tcon, full_path, &info, cifs_sb->local_nls, | 701 | rc = CIFSSMBSetPathInfo(xid, tcon, full_path, &info, cifs_sb->local_nls, |
706 | cifs_sb->mnt_cifs_flags & | 702 | cifs_remap(cifs_sb)); |
707 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
708 | if (rc == 0) | 703 | if (rc == 0) |
709 | cifsInode->cifsAttrs = dosattrs; | 704 | cifsInode->cifsAttrs = dosattrs; |
710 | } | 705 | } |
@@ -720,8 +715,7 @@ cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms, | |||
720 | oparms->create_options, | 715 | oparms->create_options, |
721 | &oparms->fid->netfid, oplock, buf, | 716 | &oparms->fid->netfid, oplock, buf, |
722 | oparms->cifs_sb->local_nls, | 717 | oparms->cifs_sb->local_nls, |
723 | oparms->cifs_sb->mnt_cifs_flags | 718 | cifs_remap(oparms->cifs_sb)); |
724 | & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
725 | return CIFS_open(xid, oparms, oplock, buf); | 719 | return CIFS_open(xid, oparms, oplock, buf); |
726 | } | 720 | } |
727 | 721 | ||
@@ -749,21 +743,21 @@ cifs_flush_file(const unsigned int xid, struct cifs_tcon *tcon, | |||
749 | } | 743 | } |
750 | 744 | ||
751 | static int | 745 | static int |
752 | cifs_sync_read(const unsigned int xid, struct cifsFileInfo *cfile, | 746 | cifs_sync_read(const unsigned int xid, struct cifs_fid *pfid, |
753 | struct cifs_io_parms *parms, unsigned int *bytes_read, | 747 | struct cifs_io_parms *parms, unsigned int *bytes_read, |
754 | char **buf, int *buf_type) | 748 | char **buf, int *buf_type) |
755 | { | 749 | { |
756 | parms->netfid = cfile->fid.netfid; | 750 | parms->netfid = pfid->netfid; |
757 | return CIFSSMBRead(xid, parms, bytes_read, buf, buf_type); | 751 | return CIFSSMBRead(xid, parms, bytes_read, buf, buf_type); |
758 | } | 752 | } |
759 | 753 | ||
760 | static int | 754 | static int |
761 | cifs_sync_write(const unsigned int xid, struct cifsFileInfo *cfile, | 755 | cifs_sync_write(const unsigned int xid, struct cifs_fid *pfid, |
762 | struct cifs_io_parms *parms, unsigned int *written, | 756 | struct cifs_io_parms *parms, unsigned int *written, |
763 | struct kvec *iov, unsigned long nr_segs) | 757 | struct kvec *iov, unsigned long nr_segs) |
764 | { | 758 | { |
765 | 759 | ||
766 | parms->netfid = cfile->fid.netfid; | 760 | parms->netfid = pfid->netfid; |
767 | return CIFSSMBWrite2(xid, parms, written, iov, nr_segs); | 761 | return CIFSSMBWrite2(xid, parms, written, iov, nr_segs); |
768 | } | 762 | } |
769 | 763 | ||
@@ -800,8 +794,7 @@ smb_set_file_info(struct inode *inode, const char *full_path, | |||
800 | tcon = tlink_tcon(tlink); | 794 | tcon = tlink_tcon(tlink); |
801 | 795 | ||
802 | rc = CIFSSMBSetPathInfo(xid, tcon, full_path, buf, cifs_sb->local_nls, | 796 | rc = CIFSSMBSetPathInfo(xid, tcon, full_path, buf, cifs_sb->local_nls, |
803 | cifs_sb->mnt_cifs_flags & | 797 | cifs_remap(cifs_sb)); |
804 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
805 | if (rc == 0) { | 798 | if (rc == 0) { |
806 | cinode->cifsAttrs = le32_to_cpu(buf->Attributes); | 799 | cinode->cifsAttrs = le32_to_cpu(buf->Attributes); |
807 | goto out; | 800 | goto out; |
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index 4aa7a0f07d6e..1a08a34838fc 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c | |||
@@ -379,6 +379,14 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb) | |||
379 | int len; | 379 | int len; |
380 | const char *start_of_path; | 380 | const char *start_of_path; |
381 | __le16 *to; | 381 | __le16 *to; |
382 | int map_type; | ||
383 | |||
384 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR) | ||
385 | map_type = SFM_MAP_UNI_RSVD; | ||
386 | else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) | ||
387 | map_type = SFU_MAP_UNI_RSVD; | ||
388 | else | ||
389 | map_type = NO_MAP_UNI_RSVD; | ||
382 | 390 | ||
383 | /* Windows doesn't allow paths beginning with \ */ | 391 | /* Windows doesn't allow paths beginning with \ */ |
384 | if (from[0] == '\\') | 392 | if (from[0] == '\\') |
@@ -386,9 +394,7 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb) | |||
386 | else | 394 | else |
387 | start_of_path = from; | 395 | start_of_path = from; |
388 | to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len, | 396 | to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len, |
389 | cifs_sb->local_nls, | 397 | cifs_sb->local_nls, map_type); |
390 | cifs_sb->mnt_cifs_flags & | ||
391 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
392 | return to; | 398 | return to; |
393 | } | 399 | } |
394 | 400 | ||
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index f522193b7184..c5f521bcdee2 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -265,15 +265,18 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon) | |||
265 | FSCTL_QUERY_NETWORK_INTERFACE_INFO, true /* is_fsctl */, | 265 | FSCTL_QUERY_NETWORK_INTERFACE_INFO, true /* is_fsctl */, |
266 | NULL /* no data input */, 0 /* no data input */, | 266 | NULL /* no data input */, 0 /* no data input */, |
267 | (char **)&out_buf, &ret_data_len); | 267 | (char **)&out_buf, &ret_data_len); |
268 | 268 | if (rc != 0) | |
269 | if ((rc == 0) && (ret_data_len > 0)) { | 269 | cifs_dbg(VFS, "error %d on ioctl to get interface list\n", rc); |
270 | else if (ret_data_len < sizeof(struct network_interface_info_ioctl_rsp)) { | ||
271 | cifs_dbg(VFS, "server returned bad net interface info buf\n"); | ||
272 | rc = -EINVAL; | ||
273 | } else { | ||
270 | /* Dump info on first interface */ | 274 | /* Dump info on first interface */ |
271 | cifs_dbg(FYI, "Adapter Capability 0x%x\t", | 275 | cifs_dbg(FYI, "Adapter Capability 0x%x\t", |
272 | le32_to_cpu(out_buf->Capability)); | 276 | le32_to_cpu(out_buf->Capability)); |
273 | cifs_dbg(FYI, "Link Speed %lld\n", | 277 | cifs_dbg(FYI, "Link Speed %lld\n", |
274 | le64_to_cpu(out_buf->LinkSpeed)); | 278 | le64_to_cpu(out_buf->LinkSpeed)); |
275 | } else | 279 | } |
276 | cifs_dbg(VFS, "error %d on ioctl to get interface list\n", rc); | ||
277 | 280 | ||
278 | return rc; | 281 | return rc; |
279 | } | 282 | } |
@@ -711,23 +714,23 @@ smb2_read_data_length(char *buf) | |||
711 | 714 | ||
712 | 715 | ||
713 | static int | 716 | static int |
714 | smb2_sync_read(const unsigned int xid, struct cifsFileInfo *cfile, | 717 | smb2_sync_read(const unsigned int xid, struct cifs_fid *pfid, |
715 | struct cifs_io_parms *parms, unsigned int *bytes_read, | 718 | struct cifs_io_parms *parms, unsigned int *bytes_read, |
716 | char **buf, int *buf_type) | 719 | char **buf, int *buf_type) |
717 | { | 720 | { |
718 | parms->persistent_fid = cfile->fid.persistent_fid; | 721 | parms->persistent_fid = pfid->persistent_fid; |
719 | parms->volatile_fid = cfile->fid.volatile_fid; | 722 | parms->volatile_fid = pfid->volatile_fid; |
720 | return SMB2_read(xid, parms, bytes_read, buf, buf_type); | 723 | return SMB2_read(xid, parms, bytes_read, buf, buf_type); |
721 | } | 724 | } |
722 | 725 | ||
723 | static int | 726 | static int |
724 | smb2_sync_write(const unsigned int xid, struct cifsFileInfo *cfile, | 727 | smb2_sync_write(const unsigned int xid, struct cifs_fid *pfid, |
725 | struct cifs_io_parms *parms, unsigned int *written, | 728 | struct cifs_io_parms *parms, unsigned int *written, |
726 | struct kvec *iov, unsigned long nr_segs) | 729 | struct kvec *iov, unsigned long nr_segs) |
727 | { | 730 | { |
728 | 731 | ||
729 | parms->persistent_fid = cfile->fid.persistent_fid; | 732 | parms->persistent_fid = pfid->persistent_fid; |
730 | parms->volatile_fid = cfile->fid.volatile_fid; | 733 | parms->volatile_fid = pfid->volatile_fid; |
731 | return SMB2_write(xid, parms, written, iov, nr_segs); | 734 | return SMB2_write(xid, parms, written, iov, nr_segs); |
732 | } | 735 | } |
733 | 736 | ||
@@ -1452,6 +1455,8 @@ struct smb_version_operations smb21_operations = { | |||
1452 | .rename = smb2_rename_path, | 1455 | .rename = smb2_rename_path, |
1453 | .create_hardlink = smb2_create_hardlink, | 1456 | .create_hardlink = smb2_create_hardlink, |
1454 | .query_symlink = smb2_query_symlink, | 1457 | .query_symlink = smb2_query_symlink, |
1458 | .query_mf_symlink = smb3_query_mf_symlink, | ||
1459 | .create_mf_symlink = smb3_create_mf_symlink, | ||
1455 | .open = smb2_open_file, | 1460 | .open = smb2_open_file, |
1456 | .set_fid = smb2_set_fid, | 1461 | .set_fid = smb2_set_fid, |
1457 | .close = smb2_close_file, | 1462 | .close = smb2_close_file, |
@@ -1531,6 +1536,8 @@ struct smb_version_operations smb30_operations = { | |||
1531 | .rename = smb2_rename_path, | 1536 | .rename = smb2_rename_path, |
1532 | .create_hardlink = smb2_create_hardlink, | 1537 | .create_hardlink = smb2_create_hardlink, |
1533 | .query_symlink = smb2_query_symlink, | 1538 | .query_symlink = smb2_query_symlink, |
1539 | .query_mf_symlink = smb3_query_mf_symlink, | ||
1540 | .create_mf_symlink = smb3_create_mf_symlink, | ||
1534 | .open = smb2_open_file, | 1541 | .open = smb2_open_file, |
1535 | .set_fid = smb2_set_fid, | 1542 | .set_fid = smb2_set_fid, |
1536 | .close = smb2_close_file, | 1543 | .close = smb2_close_file, |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 74b3a6684383..8f1672bb82d5 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -1098,6 +1098,8 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, | |||
1098 | 1098 | ||
1099 | if (oparms->create_options & CREATE_OPTION_READONLY) | 1099 | if (oparms->create_options & CREATE_OPTION_READONLY) |
1100 | file_attributes |= ATTR_READONLY; | 1100 | file_attributes |= ATTR_READONLY; |
1101 | if (oparms->create_options & CREATE_OPTION_SPECIAL) | ||
1102 | file_attributes |= ATTR_SYSTEM; | ||
1101 | 1103 | ||
1102 | req->ImpersonationLevel = IL_IMPERSONATION; | 1104 | req->ImpersonationLevel = IL_IMPERSONATION; |
1103 | req->DesiredAccess = cpu_to_le32(oparms->desired_access); | 1105 | req->DesiredAccess = cpu_to_le32(oparms->desired_access); |
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index fbe486c285a9..e3188abdafd0 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
@@ -352,6 +352,8 @@ struct smb2_tree_disconnect_rsp { | |||
352 | #define FILE_ATTRIBUTE_OFFLINE 0x00001000 | 352 | #define FILE_ATTRIBUTE_OFFLINE 0x00001000 |
353 | #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000 | 353 | #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000 |
354 | #define FILE_ATTRIBUTE_ENCRYPTED 0x00004000 | 354 | #define FILE_ATTRIBUTE_ENCRYPTED 0x00004000 |
355 | #define FILE_ATTRIBUTE_INTEGRITY_STREAM 0x00008000 | ||
356 | #define FILE_ATTRIBUTE_NO_SCRUB_DATA 0x00020000 | ||
355 | 357 | ||
356 | /* Oplock levels */ | 358 | /* Oplock levels */ |
357 | #define SMB2_OPLOCK_LEVEL_NONE 0x00 | 359 | #define SMB2_OPLOCK_LEVEL_NONE 0x00 |
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 67e8ce8055de..79dc650c18b2 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h | |||
@@ -82,7 +82,13 @@ extern int smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon, | |||
82 | extern int smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon, | 82 | extern int smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon, |
83 | const char *from_name, const char *to_name, | 83 | const char *from_name, const char *to_name, |
84 | struct cifs_sb_info *cifs_sb); | 84 | struct cifs_sb_info *cifs_sb); |
85 | 85 | extern int smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, | |
86 | struct cifs_sb_info *cifs_sb, const unsigned char *path, | ||
87 | char *pbuf, unsigned int *pbytes_written); | ||
88 | extern int smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, | ||
89 | struct cifs_sb_info *cifs_sb, | ||
90 | const unsigned char *path, char *pbuf, | ||
91 | unsigned int *pbytes_read); | ||
86 | extern int smb2_open_file(const unsigned int xid, | 92 | extern int smb2_open_file(const unsigned int xid, |
87 | struct cifs_open_parms *oparms, | 93 | struct cifs_open_parms *oparms, |
88 | __u32 *oplock, FILE_ALL_INFO *buf); | 94 | __u32 *oplock, FILE_ALL_INFO *buf); |
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c index 43eb1367b103..6c1566366a66 100644 --- a/fs/cifs/smbencrypt.c +++ b/fs/cifs/smbencrypt.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/string.h> | 29 | #include <linux/string.h> |
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/random.h> | 31 | #include <linux/random.h> |
32 | #include "cifs_fs_sb.h" | ||
32 | #include "cifs_unicode.h" | 33 | #include "cifs_unicode.h" |
33 | #include "cifspdu.h" | 34 | #include "cifspdu.h" |
34 | #include "cifsglob.h" | 35 | #include "cifsglob.h" |
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 5ac836a86b18..72a4d10653d6 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include "cifsglob.h" | 28 | #include "cifsglob.h" |
29 | #include "cifsproto.h" | 29 | #include "cifsproto.h" |
30 | #include "cifs_debug.h" | 30 | #include "cifs_debug.h" |
31 | #include "cifs_fs_sb.h" | ||
32 | #include "cifs_unicode.h" | ||
31 | 33 | ||
32 | #define MAX_EA_VALUE_SIZE 65535 | 34 | #define MAX_EA_VALUE_SIZE 65535 |
33 | #define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib" | 35 | #define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib" |
@@ -85,8 +87,7 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) | |||
85 | if (pTcon->ses->server->ops->set_EA) | 87 | if (pTcon->ses->server->ops->set_EA) |
86 | rc = pTcon->ses->server->ops->set_EA(xid, pTcon, | 88 | rc = pTcon->ses->server->ops->set_EA(xid, pTcon, |
87 | full_path, ea_name, NULL, (__u16)0, | 89 | full_path, ea_name, NULL, (__u16)0, |
88 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 90 | cifs_sb->local_nls, cifs_remap(cifs_sb)); |
89 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
90 | } | 91 | } |
91 | remove_ea_exit: | 92 | remove_ea_exit: |
92 | kfree(full_path); | 93 | kfree(full_path); |
@@ -154,8 +155,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
154 | if (pTcon->ses->server->ops->set_EA) | 155 | if (pTcon->ses->server->ops->set_EA) |
155 | rc = pTcon->ses->server->ops->set_EA(xid, pTcon, | 156 | rc = pTcon->ses->server->ops->set_EA(xid, pTcon, |
156 | full_path, ea_name, ea_value, (__u16)value_size, | 157 | full_path, ea_name, ea_value, (__u16)value_size, |
157 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 158 | cifs_sb->local_nls, cifs_remap(cifs_sb)); |
158 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
159 | } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) | 159 | } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) |
160 | == 0) { | 160 | == 0) { |
161 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) | 161 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) |
@@ -165,8 +165,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
165 | if (pTcon->ses->server->ops->set_EA) | 165 | if (pTcon->ses->server->ops->set_EA) |
166 | rc = pTcon->ses->server->ops->set_EA(xid, pTcon, | 166 | rc = pTcon->ses->server->ops->set_EA(xid, pTcon, |
167 | full_path, ea_name, ea_value, (__u16)value_size, | 167 | full_path, ea_name, ea_value, (__u16)value_size, |
168 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 168 | cifs_sb->local_nls, cifs_remap(cifs_sb)); |
169 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
170 | } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, | 169 | } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, |
171 | strlen(CIFS_XATTR_CIFS_ACL)) == 0) { | 170 | strlen(CIFS_XATTR_CIFS_ACL)) == 0) { |
172 | #ifdef CONFIG_CIFS_ACL | 171 | #ifdef CONFIG_CIFS_ACL |
@@ -199,8 +198,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
199 | rc = CIFSSMBSetPosixACL(xid, pTcon, full_path, | 198 | rc = CIFSSMBSetPosixACL(xid, pTcon, full_path, |
200 | ea_value, (const int)value_size, | 199 | ea_value, (const int)value_size, |
201 | ACL_TYPE_ACCESS, cifs_sb->local_nls, | 200 | ACL_TYPE_ACCESS, cifs_sb->local_nls, |
202 | cifs_sb->mnt_cifs_flags & | 201 | cifs_remap(cifs_sb)); |
203 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
204 | cifs_dbg(FYI, "set POSIX ACL rc %d\n", rc); | 202 | cifs_dbg(FYI, "set POSIX ACL rc %d\n", rc); |
205 | #else | 203 | #else |
206 | cifs_dbg(FYI, "set POSIX ACL not supported\n"); | 204 | cifs_dbg(FYI, "set POSIX ACL not supported\n"); |
@@ -212,8 +210,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
212 | rc = CIFSSMBSetPosixACL(xid, pTcon, full_path, | 210 | rc = CIFSSMBSetPosixACL(xid, pTcon, full_path, |
213 | ea_value, (const int)value_size, | 211 | ea_value, (const int)value_size, |
214 | ACL_TYPE_DEFAULT, cifs_sb->local_nls, | 212 | ACL_TYPE_DEFAULT, cifs_sb->local_nls, |
215 | cifs_sb->mnt_cifs_flags & | 213 | cifs_remap(cifs_sb)); |
216 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
217 | cifs_dbg(FYI, "set POSIX default ACL rc %d\n", rc); | 214 | cifs_dbg(FYI, "set POSIX default ACL rc %d\n", rc); |
218 | #else | 215 | #else |
219 | cifs_dbg(FYI, "set default POSIX ACL not supported\n"); | 216 | cifs_dbg(FYI, "set default POSIX ACL not supported\n"); |
@@ -285,8 +282,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
285 | if (pTcon->ses->server->ops->query_all_EAs) | 282 | if (pTcon->ses->server->ops->query_all_EAs) |
286 | rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, | 283 | rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, |
287 | full_path, ea_name, ea_value, buf_size, | 284 | full_path, ea_name, ea_value, buf_size, |
288 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 285 | cifs_sb->local_nls, cifs_remap(cifs_sb)); |
289 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
290 | } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { | 286 | } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { |
291 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) | 287 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) |
292 | goto get_ea_exit; | 288 | goto get_ea_exit; |
@@ -295,8 +291,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
295 | if (pTcon->ses->server->ops->query_all_EAs) | 291 | if (pTcon->ses->server->ops->query_all_EAs) |
296 | rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, | 292 | rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, |
297 | full_path, ea_name, ea_value, buf_size, | 293 | full_path, ea_name, ea_value, buf_size, |
298 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 294 | cifs_sb->local_nls, cifs_remap(cifs_sb)); |
299 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
300 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, | 295 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, |
301 | strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { | 296 | strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { |
302 | #ifdef CONFIG_CIFS_POSIX | 297 | #ifdef CONFIG_CIFS_POSIX |
@@ -304,8 +299,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
304 | rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, | 299 | rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, |
305 | ea_value, buf_size, ACL_TYPE_ACCESS, | 300 | ea_value, buf_size, ACL_TYPE_ACCESS, |
306 | cifs_sb->local_nls, | 301 | cifs_sb->local_nls, |
307 | cifs_sb->mnt_cifs_flags & | 302 | cifs_remap(cifs_sb)); |
308 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
309 | #else | 303 | #else |
310 | cifs_dbg(FYI, "Query POSIX ACL not supported yet\n"); | 304 | cifs_dbg(FYI, "Query POSIX ACL not supported yet\n"); |
311 | #endif /* CONFIG_CIFS_POSIX */ | 305 | #endif /* CONFIG_CIFS_POSIX */ |
@@ -316,8 +310,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
316 | rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, | 310 | rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, |
317 | ea_value, buf_size, ACL_TYPE_DEFAULT, | 311 | ea_value, buf_size, ACL_TYPE_DEFAULT, |
318 | cifs_sb->local_nls, | 312 | cifs_sb->local_nls, |
319 | cifs_sb->mnt_cifs_flags & | 313 | cifs_remap(cifs_sb)); |
320 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
321 | #else | 314 | #else |
322 | cifs_dbg(FYI, "Query POSIX default ACL not supported yet\n"); | 315 | cifs_dbg(FYI, "Query POSIX default ACL not supported yet\n"); |
323 | #endif /* CONFIG_CIFS_POSIX */ | 316 | #endif /* CONFIG_CIFS_POSIX */ |
@@ -421,8 +414,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) | |||
421 | if (pTcon->ses->server->ops->query_all_EAs) | 414 | if (pTcon->ses->server->ops->query_all_EAs) |
422 | rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, | 415 | rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, |
423 | full_path, NULL, data, buf_size, | 416 | full_path, NULL, data, buf_size, |
424 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 417 | cifs_sb->local_nls, cifs_remap(cifs_sb)); |
425 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
426 | list_ea_exit: | 418 | list_ea_exit: |
427 | kfree(full_path); | 419 | kfree(full_path); |
428 | free_xid(xid); | 420 | free_xid(xid); |