diff options
| -rw-r--r-- | fs/cifs/cifs_fs_sb.h | 1 | ||||
| -rw-r--r-- | fs/cifs/cifs_unicode.c | 127 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.c | 38 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.h | 13 | ||||
| -rw-r--r-- | fs/cifs/cifsglob.h | 36 | ||||
| -rw-r--r-- | fs/cifs/cifspdu.h | 47 | ||||
| -rw-r--r-- | fs/cifs/cifssmb.c | 54 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 43 | ||||
| -rw-r--r-- | fs/cifs/file.c | 175 | ||||
| -rw-r--r-- | fs/cifs/inode.c | 8 | ||||
| -rw-r--r-- | fs/cifs/misc.c | 71 | ||||
| -rw-r--r-- | fs/cifs/netmisc.c | 4 | ||||
| -rw-r--r-- | fs/cifs/sess.c | 13 | ||||
| -rw-r--r-- | fs/cifs/transport.c | 9 |
14 files changed, 402 insertions, 237 deletions
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index 7852cd677051..ac51cd2d33ae 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #define CIFS_MOUNT_FSCACHE 0x8000 /* local caching enabled */ | 40 | #define CIFS_MOUNT_FSCACHE 0x8000 /* local caching enabled */ |
| 41 | #define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */ | 41 | #define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */ |
| 42 | #define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ | 42 | #define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ |
| 43 | #define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */ | ||
| 43 | 44 | ||
| 44 | struct cifs_sb_info { | 45 | struct cifs_sb_info { |
| 45 | struct rb_root tlink_tree; | 46 | struct rb_root tlink_tree; |
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index 430f510a1720..fc0fd4fde306 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c | |||
| @@ -44,10 +44,14 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes, | |||
| 44 | int charlen, outlen = 0; | 44 | int charlen, outlen = 0; |
| 45 | int maxwords = maxbytes / 2; | 45 | int maxwords = maxbytes / 2; |
| 46 | char tmp[NLS_MAX_CHARSET_SIZE]; | 46 | char tmp[NLS_MAX_CHARSET_SIZE]; |
| 47 | __u16 ftmp; | ||
| 47 | 48 | ||
| 48 | for (i = 0; i < maxwords && from[i]; i++) { | 49 | for (i = 0; i < maxwords; i++) { |
| 49 | charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp, | 50 | ftmp = get_unaligned_le16(&from[i]); |
| 50 | NLS_MAX_CHARSET_SIZE); | 51 | if (ftmp == 0) |
| 52 | break; | ||
| 53 | |||
| 54 | charlen = codepage->uni2char(ftmp, tmp, NLS_MAX_CHARSET_SIZE); | ||
| 51 | if (charlen > 0) | 55 | if (charlen > 0) |
| 52 | outlen += charlen; | 56 | outlen += charlen; |
| 53 | else | 57 | else |
| @@ -58,9 +62,9 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes, | |||
| 58 | } | 62 | } |
| 59 | 63 | ||
| 60 | /* | 64 | /* |
| 61 | * cifs_mapchar - convert a little-endian char to proper char in codepage | 65 | * cifs_mapchar - convert a host-endian char to proper char in codepage |
| 62 | * @target - where converted character should be copied | 66 | * @target - where converted character should be copied |
| 63 | * @src_char - 2 byte little-endian source character | 67 | * @src_char - 2 byte host-endian source character |
| 64 | * @cp - codepage to which character should be converted | 68 | * @cp - codepage to which character should be converted |
| 65 | * @mapchar - should character be mapped according to mapchars mount option? | 69 | * @mapchar - should character be mapped according to mapchars mount option? |
| 66 | * | 70 | * |
| @@ -69,7 +73,7 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes, | |||
| 69 | * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE). | 73 | * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE). |
| 70 | */ | 74 | */ |
| 71 | static int | 75 | static int |
| 72 | cifs_mapchar(char *target, const __le16 src_char, const struct nls_table *cp, | 76 | cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, |
| 73 | bool mapchar) | 77 | bool mapchar) |
| 74 | { | 78 | { |
| 75 | int len = 1; | 79 | int len = 1; |
| @@ -82,7 +86,7 @@ cifs_mapchar(char *target, const __le16 src_char, const struct nls_table *cp, | |||
| 82 | * build_path_from_dentry are modified, as they use slash as | 86 | * build_path_from_dentry are modified, as they use slash as |
| 83 | * separator. | 87 | * separator. |
| 84 | */ | 88 | */ |
| 85 | switch (le16_to_cpu(src_char)) { | 89 | switch (src_char) { |
| 86 | case UNI_COLON: | 90 | case UNI_COLON: |
| 87 | *target = ':'; | 91 | *target = ':'; |
| 88 | break; | 92 | break; |
| @@ -109,8 +113,7 @@ out: | |||
| 109 | return len; | 113 | return len; |
| 110 | 114 | ||
| 111 | cp_convert: | 115 | cp_convert: |
| 112 | len = cp->uni2char(le16_to_cpu(src_char), target, | 116 | len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE); |
| 113 | NLS_MAX_CHARSET_SIZE); | ||
| 114 | if (len <= 0) { | 117 | if (len <= 0) { |
| 115 | *target = '?'; | 118 | *target = '?'; |
| 116 | len = 1; | 119 | len = 1; |
| @@ -149,6 +152,7 @@ cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen, | |||
| 149 | int nullsize = nls_nullsize(codepage); | 152 | int nullsize = nls_nullsize(codepage); |
| 150 | int fromwords = fromlen / 2; | 153 | int fromwords = fromlen / 2; |
| 151 | char tmp[NLS_MAX_CHARSET_SIZE]; | 154 | char tmp[NLS_MAX_CHARSET_SIZE]; |
| 155 | __u16 ftmp; | ||
| 152 | 156 | ||
| 153 | /* | 157 | /* |
| 154 | * because the chars can be of varying widths, we need to take care | 158 | * because the chars can be of varying widths, we need to take care |
| @@ -158,19 +162,23 @@ cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen, | |||
| 158 | */ | 162 | */ |
| 159 | safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize); | 163 | safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize); |
| 160 | 164 | ||
| 161 | for (i = 0; i < fromwords && from[i]; i++) { | 165 | for (i = 0; i < fromwords; i++) { |
| 166 | ftmp = get_unaligned_le16(&from[i]); | ||
| 167 | if (ftmp == 0) | ||
| 168 | break; | ||
| 169 | |||
| 162 | /* | 170 | /* |
| 163 | * check to see if converting this character might make the | 171 | * check to see if converting this character might make the |
| 164 | * conversion bleed into the null terminator | 172 | * conversion bleed into the null terminator |
| 165 | */ | 173 | */ |
| 166 | if (outlen >= safelen) { | 174 | if (outlen >= safelen) { |
| 167 | charlen = cifs_mapchar(tmp, from[i], codepage, mapchar); | 175 | charlen = cifs_mapchar(tmp, ftmp, codepage, mapchar); |
| 168 | if ((outlen + charlen) > (tolen - nullsize)) | 176 | if ((outlen + charlen) > (tolen - nullsize)) |
| 169 | break; | 177 | break; |
| 170 | } | 178 | } |
| 171 | 179 | ||
| 172 | /* put converted char into 'to' buffer */ | 180 | /* put converted char into 'to' buffer */ |
| 173 | charlen = cifs_mapchar(&to[outlen], from[i], codepage, mapchar); | 181 | charlen = cifs_mapchar(&to[outlen], ftmp, codepage, mapchar); |
| 174 | outlen += charlen; | 182 | outlen += charlen; |
| 175 | } | 183 | } |
| 176 | 184 | ||
| @@ -193,24 +201,21 @@ cifs_strtoUCS(__le16 *to, const char *from, int len, | |||
| 193 | { | 201 | { |
| 194 | int charlen; | 202 | int charlen; |
| 195 | int i; | 203 | int i; |
| 196 | wchar_t *wchar_to = (wchar_t *)to; /* needed to quiet sparse */ | 204 | wchar_t wchar_to; /* needed to quiet sparse */ |
| 197 | 205 | ||
| 198 | for (i = 0; len && *from; i++, from += charlen, len -= charlen) { | 206 | for (i = 0; len && *from; i++, from += charlen, len -= charlen) { |
| 199 | 207 | charlen = codepage->char2uni(from, len, &wchar_to); | |
| 200 | /* works for 2.4.0 kernel or later */ | ||
| 201 | charlen = codepage->char2uni(from, len, &wchar_to[i]); | ||
| 202 | if (charlen < 1) { | 208 | if (charlen < 1) { |
| 203 | cERROR(1, "strtoUCS: char2uni of %d returned %d", | 209 | cERROR(1, "strtoUCS: char2uni of 0x%x returned %d", |
| 204 | (int)*from, charlen); | 210 | *from, charlen); |
| 205 | /* A question mark */ | 211 | /* A question mark */ |
| 206 | to[i] = cpu_to_le16(0x003f); | 212 | wchar_to = 0x003f; |
| 207 | charlen = 1; | 213 | charlen = 1; |
| 208 | } else | 214 | } |
| 209 | to[i] = cpu_to_le16(wchar_to[i]); | 215 | put_unaligned_le16(wchar_to, &to[i]); |
| 210 | |||
| 211 | } | 216 | } |
| 212 | 217 | ||
| 213 | to[i] = 0; | 218 | put_unaligned_le16(0, &to[i]); |
| 214 | return i; | 219 | return i; |
| 215 | } | 220 | } |
| 216 | 221 | ||
| @@ -252,3 +257,79 @@ cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode, | |||
| 252 | return dst; | 257 | return dst; |
| 253 | } | 258 | } |
| 254 | 259 | ||
| 260 | /* | ||
| 261 | * Convert 16 bit Unicode pathname to wire format from string in current code | ||
| 262 | * page. Conversion may involve remapping up the six characters that are | ||
| 263 | * only legal in POSIX-like OS (if they are present in the string). Path | ||
| 264 | * names are little endian 16 bit Unicode on the wire | ||
| 265 | */ | ||
| 266 | int | ||
| 267 | cifsConvertToUCS(__le16 *target, const char *source, int maxlen, | ||
| 268 | const struct nls_table *cp, int mapChars) | ||
| 269 | { | ||
| 270 | int i, j, charlen; | ||
| 271 | int len_remaining = maxlen; | ||
| 272 | char src_char; | ||
| 273 | __u16 temp; | ||
| 274 | |||
| 275 | if (!mapChars) | ||
| 276 | return cifs_strtoUCS(target, source, PATH_MAX, cp); | ||
| 277 | |||
| 278 | for (i = 0, j = 0; i < maxlen; j++) { | ||
| 279 | src_char = source[i]; | ||
| 280 | switch (src_char) { | ||
| 281 | case 0: | ||
| 282 | put_unaligned_le16(0, &target[j]); | ||
| 283 | goto ctoUCS_out; | ||
| 284 | case ':': | ||
| 285 | temp = UNI_COLON; | ||
| 286 | break; | ||
| 287 | case '*': | ||
| 288 | temp = UNI_ASTERIK; | ||
| 289 | break; | ||
| 290 | case '?': | ||
| 291 | temp = UNI_QUESTION; | ||
| 292 | break; | ||
| 293 | case '<': | ||
| 294 | temp = UNI_LESSTHAN; | ||
| 295 | break; | ||
| 296 | case '>': | ||
| 297 | temp = UNI_GRTRTHAN; | ||
| 298 | break; | ||
| 299 | case '|': | ||
| 300 | temp = UNI_PIPE; | ||
| 301 | break; | ||
| 302 | /* | ||
| 303 | * FIXME: We can not handle remapping backslash (UNI_SLASH) | ||
| 304 | * until all the calls to build_path_from_dentry are modified, | ||
| 305 | * as they use backslash as separator. | ||
| 306 | */ | ||
| 307 | default: | ||
| 308 | charlen = cp->char2uni(source+i, len_remaining, | ||
| 309 | &temp); | ||
| 310 | /* | ||
| 311 | * if no match, use question mark, which at least in | ||
| 312 | * some cases serves as wild card | ||
| 313 | */ | ||
| 314 | if (charlen < 1) { | ||
| 315 | temp = 0x003f; | ||
| 316 | charlen = 1; | ||
| 317 | } | ||
| 318 | len_remaining -= charlen; | ||
| 319 | /* | ||
| 320 | * character may take more than one byte in the source | ||
| 321 | * string, but will take exactly two bytes in the | ||
| 322 | * target string | ||
| 323 | */ | ||
| 324 | i += charlen; | ||
| 325 | continue; | ||
| 326 | } | ||
| 327 | put_unaligned_le16(temp, &target[j]); | ||
| 328 | i++; /* move to next char in source string */ | ||
| 329 | len_remaining--; | ||
| 330 | } | ||
| 331 | |||
| 332 | ctoUCS_out: | ||
| 333 | return i; | ||
| 334 | } | ||
| 335 | |||
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 99d777a03dd0..a8323f1dc1c4 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -733,6 +733,25 @@ const struct file_operations cifs_file_ops = { | |||
| 733 | .setlease = cifs_setlease, | 733 | .setlease = cifs_setlease, |
| 734 | }; | 734 | }; |
| 735 | 735 | ||
| 736 | const struct file_operations cifs_file_strict_ops = { | ||
| 737 | .read = do_sync_read, | ||
| 738 | .write = do_sync_write, | ||
| 739 | .aio_read = cifs_strict_readv, | ||
| 740 | .aio_write = cifs_file_aio_write, | ||
| 741 | .open = cifs_open, | ||
| 742 | .release = cifs_close, | ||
| 743 | .lock = cifs_lock, | ||
| 744 | .fsync = cifs_strict_fsync, | ||
| 745 | .flush = cifs_flush, | ||
| 746 | .mmap = cifs_file_strict_mmap, | ||
| 747 | .splice_read = generic_file_splice_read, | ||
| 748 | .llseek = cifs_llseek, | ||
| 749 | #ifdef CONFIG_CIFS_POSIX | ||
| 750 | .unlocked_ioctl = cifs_ioctl, | ||
| 751 | #endif /* CONFIG_CIFS_POSIX */ | ||
| 752 | .setlease = cifs_setlease, | ||
| 753 | }; | ||
| 754 | |||
| 736 | const struct file_operations cifs_file_direct_ops = { | 755 | const struct file_operations cifs_file_direct_ops = { |
| 737 | /* no aio, no readv - | 756 | /* no aio, no readv - |
| 738 | BB reevaluate whether they can be done with directio, no cache */ | 757 | BB reevaluate whether they can be done with directio, no cache */ |
| @@ -751,6 +770,7 @@ const struct file_operations cifs_file_direct_ops = { | |||
| 751 | .llseek = cifs_llseek, | 770 | .llseek = cifs_llseek, |
| 752 | .setlease = cifs_setlease, | 771 | .setlease = cifs_setlease, |
| 753 | }; | 772 | }; |
| 773 | |||
| 754 | const struct file_operations cifs_file_nobrl_ops = { | 774 | const struct file_operations cifs_file_nobrl_ops = { |
| 755 | .read = do_sync_read, | 775 | .read = do_sync_read, |
| 756 | .write = do_sync_write, | 776 | .write = do_sync_write, |
| @@ -769,6 +789,24 @@ const struct file_operations cifs_file_nobrl_ops = { | |||
| 769 | .setlease = cifs_setlease, | 789 | .setlease = cifs_setlease, |
| 770 | }; | 790 | }; |
| 771 | 791 | ||
| 792 | const struct file_operations cifs_file_strict_nobrl_ops = { | ||
| 793 | .read = do_sync_read, | ||
| 794 | .write = do_sync_write, | ||
| 795 | .aio_read = cifs_strict_readv, | ||
| 796 | .aio_write = cifs_file_aio_write, | ||
| 797 | .open = cifs_open, | ||
| 798 | .release = cifs_close, | ||
| 799 | .fsync = cifs_strict_fsync, | ||
| 800 | .flush = cifs_flush, | ||
| 801 | .mmap = cifs_file_strict_mmap, | ||
| 802 | .splice_read = generic_file_splice_read, | ||
| 803 | .llseek = cifs_llseek, | ||
| 804 | #ifdef CONFIG_CIFS_POSIX | ||
| 805 | .unlocked_ioctl = cifs_ioctl, | ||
| 806 | #endif /* CONFIG_CIFS_POSIX */ | ||
| 807 | .setlease = cifs_setlease, | ||
| 808 | }; | ||
| 809 | |||
| 772 | const struct file_operations cifs_file_direct_nobrl_ops = { | 810 | const struct file_operations cifs_file_direct_nobrl_ops = { |
| 773 | /* no mmap, no aio, no readv - | 811 | /* no mmap, no aio, no readv - |
| 774 | BB reevaluate whether they can be done with directio, no cache */ | 812 | BB reevaluate whether they can be done with directio, no cache */ |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 4739a531cded..f23206d46531 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
| @@ -61,6 +61,7 @@ extern int cifs_rename(struct inode *, struct dentry *, struct inode *, | |||
| 61 | struct dentry *); | 61 | struct dentry *); |
| 62 | extern int cifs_revalidate_file(struct file *filp); | 62 | extern int cifs_revalidate_file(struct file *filp); |
| 63 | extern int cifs_revalidate_dentry(struct dentry *); | 63 | extern int cifs_revalidate_dentry(struct dentry *); |
| 64 | extern void cifs_invalidate_mapping(struct inode *inode); | ||
| 64 | extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); | 65 | extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); |
| 65 | extern int cifs_setattr(struct dentry *, struct iattr *); | 66 | extern int cifs_setattr(struct dentry *, struct iattr *); |
| 66 | 67 | ||
| @@ -72,19 +73,25 @@ extern const struct inode_operations cifs_dfs_referral_inode_operations; | |||
| 72 | /* Functions related to files and directories */ | 73 | /* Functions related to files and directories */ |
| 73 | extern const struct file_operations cifs_file_ops; | 74 | extern const struct file_operations cifs_file_ops; |
| 74 | extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */ | 75 | extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */ |
| 75 | extern const struct file_operations cifs_file_nobrl_ops; | 76 | extern const struct file_operations cifs_file_strict_ops; /* if strictio mnt */ |
| 76 | extern const struct file_operations cifs_file_direct_nobrl_ops; /* no brlocks */ | 77 | extern const struct file_operations cifs_file_nobrl_ops; /* no brlocks */ |
| 78 | extern const struct file_operations cifs_file_direct_nobrl_ops; | ||
| 79 | extern const struct file_operations cifs_file_strict_nobrl_ops; | ||
| 77 | extern int cifs_open(struct inode *inode, struct file *file); | 80 | extern int cifs_open(struct inode *inode, struct file *file); |
| 78 | extern int cifs_close(struct inode *inode, struct file *file); | 81 | extern int cifs_close(struct inode *inode, struct file *file); |
| 79 | extern int cifs_closedir(struct inode *inode, struct file *file); | 82 | extern int cifs_closedir(struct inode *inode, struct file *file); |
| 80 | extern ssize_t cifs_user_read(struct file *file, char __user *read_data, | 83 | extern ssize_t cifs_user_read(struct file *file, char __user *read_data, |
| 81 | size_t read_size, loff_t *poffset); | 84 | size_t read_size, loff_t *poffset); |
| 85 | extern ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov, | ||
| 86 | unsigned long nr_segs, loff_t pos); | ||
| 82 | extern ssize_t cifs_user_write(struct file *file, const char __user *write_data, | 87 | extern ssize_t cifs_user_write(struct file *file, const char __user *write_data, |
| 83 | size_t write_size, loff_t *poffset); | 88 | size_t write_size, loff_t *poffset); |
| 84 | extern int cifs_lock(struct file *, int, struct file_lock *); | 89 | extern int cifs_lock(struct file *, int, struct file_lock *); |
| 85 | extern int cifs_fsync(struct file *, int); | 90 | extern int cifs_fsync(struct file *, int); |
| 91 | extern int cifs_strict_fsync(struct file *, int); | ||
| 86 | extern int cifs_flush(struct file *, fl_owner_t id); | 92 | extern int cifs_flush(struct file *, fl_owner_t id); |
| 87 | extern int cifs_file_mmap(struct file * , struct vm_area_struct *); | 93 | extern int cifs_file_mmap(struct file * , struct vm_area_struct *); |
| 94 | extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *); | ||
| 88 | extern const struct file_operations cifs_dir_ops; | 95 | extern const struct file_operations cifs_dir_ops; |
| 89 | extern int cifs_dir_open(struct inode *inode, struct file *file); | 96 | extern int cifs_dir_open(struct inode *inode, struct file *file); |
| 90 | extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); | 97 | extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 571132c95231..5bfb75346cb0 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -161,6 +161,7 @@ struct TCP_Server_Info { | |||
| 161 | int srv_count; /* reference counter */ | 161 | int srv_count; /* reference counter */ |
| 162 | /* 15 character server name + 0x20 16th byte indicating type = srv */ | 162 | /* 15 character server name + 0x20 16th byte indicating type = srv */ |
| 163 | char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; | 163 | char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; |
| 164 | enum statusEnum tcpStatus; /* what we think the status is */ | ||
| 164 | char *hostname; /* hostname portion of UNC string */ | 165 | char *hostname; /* hostname portion of UNC string */ |
| 165 | struct socket *ssocket; | 166 | struct socket *ssocket; |
| 166 | struct sockaddr_storage dstaddr; | 167 | struct sockaddr_storage dstaddr; |
| @@ -168,25 +169,16 @@ struct TCP_Server_Info { | |||
| 168 | wait_queue_head_t response_q; | 169 | wait_queue_head_t response_q; |
| 169 | wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/ | 170 | wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/ |
| 170 | struct list_head pending_mid_q; | 171 | struct list_head pending_mid_q; |
| 171 | void *Server_NlsInfo; /* BB - placeholder for future NLS info */ | ||
| 172 | unsigned short server_codepage; /* codepage for the server */ | ||
| 173 | enum protocolEnum protocolType; | ||
| 174 | char versionMajor; | ||
| 175 | char versionMinor; | ||
| 176 | bool svlocal:1; /* local server or remote */ | ||
| 177 | bool noblocksnd; /* use blocking sendmsg */ | 172 | bool noblocksnd; /* use blocking sendmsg */ |
| 178 | bool noautotune; /* do not autotune send buf sizes */ | 173 | bool noautotune; /* do not autotune send buf sizes */ |
| 179 | bool tcp_nodelay; | 174 | bool tcp_nodelay; |
| 180 | atomic_t inFlight; /* number of requests on the wire to server */ | 175 | atomic_t inFlight; /* number of requests on the wire to server */ |
| 181 | #ifdef CONFIG_CIFS_STATS2 | ||
| 182 | atomic_t inSend; /* requests trying to send */ | ||
| 183 | atomic_t num_waiters; /* blocked waiting to get in sendrecv */ | ||
| 184 | #endif | ||
| 185 | enum statusEnum tcpStatus; /* what we think the status is */ | ||
| 186 | struct mutex srv_mutex; | 176 | struct mutex srv_mutex; |
| 187 | struct task_struct *tsk; | 177 | struct task_struct *tsk; |
| 188 | char server_GUID[16]; | 178 | char server_GUID[16]; |
| 189 | char secMode; | 179 | char secMode; |
| 180 | bool session_estab; /* mark when very first sess is established */ | ||
| 181 | u16 dialect; /* dialect index that server chose */ | ||
| 190 | enum securityEnum secType; | 182 | enum securityEnum secType; |
| 191 | unsigned int maxReq; /* Clients should submit no more */ | 183 | unsigned int maxReq; /* Clients should submit no more */ |
| 192 | /* than maxReq distinct unanswered SMBs to the server when using */ | 184 | /* than maxReq distinct unanswered SMBs to the server when using */ |
| @@ -199,8 +191,6 @@ struct TCP_Server_Info { | |||
| 199 | unsigned int max_vcs; /* maximum number of smb sessions, at least | 191 | unsigned int max_vcs; /* maximum number of smb sessions, at least |
| 200 | those that can be specified uniquely with | 192 | those that can be specified uniquely with |
| 201 | vcnumbers */ | 193 | vcnumbers */ |
| 202 | char sessid[4]; /* unique token id for this session */ | ||
| 203 | /* (returned on Negotiate */ | ||
| 204 | int capabilities; /* allow selective disabling of caps by smb sess */ | 194 | int capabilities; /* allow selective disabling of caps by smb sess */ |
| 205 | int timeAdj; /* Adjust for difference in server time zone in sec */ | 195 | int timeAdj; /* Adjust for difference in server time zone in sec */ |
| 206 | __u16 CurrentMid; /* multiplex id - rotating counter */ | 196 | __u16 CurrentMid; /* multiplex id - rotating counter */ |
| @@ -210,18 +200,20 @@ struct TCP_Server_Info { | |||
| 210 | __u32 sequence_number; /* for signing, protected by srv_mutex */ | 200 | __u32 sequence_number; /* for signing, protected by srv_mutex */ |
| 211 | struct session_key session_key; | 201 | struct session_key session_key; |
| 212 | unsigned long lstrp; /* when we got last response from this server */ | 202 | unsigned long lstrp; /* when we got last response from this server */ |
| 213 | u16 dialect; /* dialect index that server chose */ | ||
| 214 | struct cifs_secmech secmech; /* crypto sec mech functs, descriptors */ | 203 | struct cifs_secmech secmech; /* crypto sec mech functs, descriptors */ |
| 215 | /* extended security flavors that server supports */ | 204 | /* extended security flavors that server supports */ |
| 205 | bool sec_ntlmssp; /* supports NTLMSSP */ | ||
| 206 | bool sec_kerberosu2u; /* supports U2U Kerberos */ | ||
| 216 | bool sec_kerberos; /* supports plain Kerberos */ | 207 | bool sec_kerberos; /* supports plain Kerberos */ |
| 217 | bool sec_mskerberos; /* supports legacy MS Kerberos */ | 208 | bool sec_mskerberos; /* supports legacy MS Kerberos */ |
| 218 | bool sec_kerberosu2u; /* supports U2U Kerberos */ | ||
| 219 | bool sec_ntlmssp; /* supports NTLMSSP */ | ||
| 220 | bool session_estab; /* mark when very first sess is established */ | ||
| 221 | struct delayed_work echo; /* echo ping workqueue job */ | 209 | struct delayed_work echo; /* echo ping workqueue job */ |
| 222 | #ifdef CONFIG_CIFS_FSCACHE | 210 | #ifdef CONFIG_CIFS_FSCACHE |
| 223 | struct fscache_cookie *fscache; /* client index cache cookie */ | 211 | struct fscache_cookie *fscache; /* client index cache cookie */ |
| 224 | #endif | 212 | #endif |
| 213 | #ifdef CONFIG_CIFS_STATS2 | ||
| 214 | atomic_t inSend; /* requests trying to send */ | ||
| 215 | atomic_t num_waiters; /* blocked waiting to get in sendrecv */ | ||
| 216 | #endif | ||
| 225 | }; | 217 | }; |
| 226 | 218 | ||
| 227 | /* | 219 | /* |
| @@ -447,11 +439,11 @@ struct cifsInodeInfo { | |||
| 447 | /* BB add in lists for dirty pages i.e. write caching info for oplock */ | 439 | /* BB add in lists for dirty pages i.e. write caching info for oplock */ |
| 448 | struct list_head openFileList; | 440 | struct list_head openFileList; |
| 449 | __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ | 441 | __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ |
| 450 | unsigned long time; /* jiffies of last update/check of inode */ | 442 | bool clientCanCacheRead; /* read oplock */ |
| 451 | bool clientCanCacheRead:1; /* read oplock */ | 443 | bool clientCanCacheAll; /* read and writebehind oplock */ |
| 452 | bool clientCanCacheAll:1; /* read and writebehind oplock */ | 444 | bool delete_pending; /* DELETE_ON_CLOSE is set */ |
| 453 | bool delete_pending:1; /* DELETE_ON_CLOSE is set */ | 445 | bool invalid_mapping; /* pagecache is invalid */ |
| 454 | bool invalid_mapping:1; /* pagecache is invalid */ | 446 | unsigned long time; /* jiffies of last update of inode */ |
| 455 | u64 server_eof; /* current file size on server */ | 447 | u64 server_eof; /* current file size on server */ |
| 456 | u64 uniqueid; /* server inode number */ | 448 | u64 uniqueid; /* server inode number */ |
| 457 | u64 createtime; /* creation time on server */ | 449 | u64 createtime; /* creation time on server */ |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index ea205b4fcad2..b5c8cc5d7a7f 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #define _CIFSPDU_H | 23 | #define _CIFSPDU_H |
| 24 | 24 | ||
| 25 | #include <net/sock.h> | 25 | #include <net/sock.h> |
| 26 | #include <asm/unaligned.h> | ||
| 26 | #include "smbfsctl.h" | 27 | #include "smbfsctl.h" |
| 27 | 28 | ||
| 28 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 29 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
| @@ -426,11 +427,49 @@ struct smb_hdr { | |||
| 426 | __u16 Mid; | 427 | __u16 Mid; |
| 427 | __u8 WordCount; | 428 | __u8 WordCount; |
| 428 | } __attribute__((packed)); | 429 | } __attribute__((packed)); |
| 429 | /* given a pointer to an smb_hdr retrieve the value of byte count */ | 430 | |
| 430 | #define BCC(smb_var) (*(__u16 *)((char *)(smb_var) + sizeof(struct smb_hdr) + (2 * (smb_var)->WordCount))) | 431 | /* given a pointer to an smb_hdr retrieve a char pointer to the byte count */ |
| 431 | #define BCC_LE(smb_var) (*(__le16 *)((char *)(smb_var) + sizeof(struct smb_hdr) + (2 * (smb_var)->WordCount))) | 432 | #define BCC(smb_var) ((unsigned char *)(smb_var) + sizeof(struct smb_hdr) + \ |
| 433 | (2 * (smb_var)->WordCount)) | ||
| 434 | |||
| 432 | /* given a pointer to an smb_hdr retrieve the pointer to the byte area */ | 435 | /* given a pointer to an smb_hdr retrieve the pointer to the byte area */ |
| 433 | #define pByteArea(smb_var) ((unsigned char *)(smb_var) + sizeof(struct smb_hdr) + (2 * (smb_var)->WordCount) + 2) | 436 | #define pByteArea(smb_var) (BCC(smb_var) + 2) |
| 437 | |||
| 438 | /* get the converted ByteCount for a SMB packet and return it */ | ||
| 439 | static inline __u16 | ||
| 440 | get_bcc(struct smb_hdr *hdr) | ||
| 441 | { | ||
| 442 | __u16 *bc_ptr = (__u16 *)BCC(hdr); | ||
| 443 | |||
| 444 | return get_unaligned(bc_ptr); | ||
| 445 | } | ||
| 446 | |||
| 447 | /* get the unconverted ByteCount for a SMB packet and return it */ | ||
| 448 | static inline __u16 | ||
| 449 | get_bcc_le(struct smb_hdr *hdr) | ||
| 450 | { | ||
| 451 | __le16 *bc_ptr = (__le16 *)BCC(hdr); | ||
| 452 | |||
| 453 | return get_unaligned_le16(bc_ptr); | ||
| 454 | } | ||
| 455 | |||
| 456 | /* set the ByteCount for a SMB packet in host-byte order */ | ||
| 457 | static inline void | ||
| 458 | put_bcc(__u16 count, struct smb_hdr *hdr) | ||
| 459 | { | ||
| 460 | __u16 *bc_ptr = (__u16 *)BCC(hdr); | ||
| 461 | |||
| 462 | put_unaligned(count, bc_ptr); | ||
| 463 | } | ||
| 464 | |||
| 465 | /* set the ByteCount for a SMB packet in little-endian */ | ||
| 466 | static inline void | ||
| 467 | put_bcc_le(__u16 count, struct smb_hdr *hdr) | ||
| 468 | { | ||
| 469 | __le16 *bc_ptr = (__le16 *)BCC(hdr); | ||
| 470 | |||
| 471 | put_unaligned_le16(count, bc_ptr); | ||
| 472 | } | ||
| 434 | 473 | ||
| 435 | /* | 474 | /* |
| 436 | * Computer Name Length (since Netbios name was length 16 with last byte 0x20) | 475 | * Computer Name Length (since Netbios name was length 16 with last byte 0x20) |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 37113450757b..675041a6949c 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -331,37 +331,35 @@ smb_init_no_reconnect(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
| 331 | 331 | ||
| 332 | static int validate_t2(struct smb_t2_rsp *pSMB) | 332 | static int validate_t2(struct smb_t2_rsp *pSMB) |
| 333 | { | 333 | { |
| 334 | int rc = -EINVAL; | 334 | unsigned int total_size; |
| 335 | int total_size; | 335 | |
| 336 | char *pBCC; | 336 | /* check for plausible wct */ |
| 337 | if (pSMB->hdr.WordCount < 10) | ||
| 338 | goto vt2_err; | ||
| 337 | 339 | ||
| 338 | /* check for plausible wct, bcc and t2 data and parm sizes */ | ||
| 339 | /* check for parm and data offset going beyond end of smb */ | 340 | /* check for parm and data offset going beyond end of smb */ |
| 340 | if (pSMB->hdr.WordCount >= 10) { | 341 | if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 || |
| 341 | if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) && | 342 | get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024) |
| 342 | (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) { | 343 | goto vt2_err; |
| 343 | /* check that bcc is at least as big as parms + data */ | 344 | |
| 344 | /* check that bcc is less than negotiated smb buffer */ | 345 | /* check that bcc is at least as big as parms + data */ |
| 345 | total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount); | 346 | /* check that bcc is less than negotiated smb buffer */ |
| 346 | if (total_size < 512) { | 347 | total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount); |
| 347 | total_size += | 348 | if (total_size >= 512) |
| 348 | le16_to_cpu(pSMB->t2_rsp.DataCount); | 349 | goto vt2_err; |
| 349 | /* BCC le converted in SendReceive */ | 350 | |
| 350 | pBCC = (pSMB->hdr.WordCount * 2) + | 351 | total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount); |
| 351 | sizeof(struct smb_hdr) + | 352 | if (total_size > get_bcc(&pSMB->hdr) || |
| 352 | (char *)pSMB; | 353 | total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) |
| 353 | if ((total_size <= (*(u16 *)pBCC)) && | 354 | goto vt2_err; |
| 354 | (total_size < | 355 | |
| 355 | CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) { | 356 | return 0; |
| 356 | return 0; | 357 | vt2_err: |
| 357 | } | ||
| 358 | } | ||
| 359 | } | ||
| 360 | } | ||
| 361 | cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB, | 358 | cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB, |
| 362 | sizeof(struct smb_t2_rsp) + 16); | 359 | sizeof(struct smb_t2_rsp) + 16); |
| 363 | return rc; | 360 | return -EINVAL; |
| 364 | } | 361 | } |
| 362 | |||
| 365 | int | 363 | int |
| 366 | CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | 364 | CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) |
| 367 | { | 365 | { |
| @@ -452,7 +450,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
| 452 | server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), | 450 | server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), |
| 453 | (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); | 451 | (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); |
| 454 | server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); | 452 | server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); |
| 455 | GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey); | ||
| 456 | /* even though we do not use raw we might as well set this | 453 | /* even though we do not use raw we might as well set this |
| 457 | accurately, in case we ever find a need for it */ | 454 | accurately, in case we ever find a need for it */ |
| 458 | if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { | 455 | if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { |
| @@ -566,7 +563,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
| 566 | (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); | 563 | (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); |
| 567 | server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); | 564 | server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); |
| 568 | cFYI(DBG2, "Max buf = %d", ses->server->maxBuf); | 565 | cFYI(DBG2, "Max buf = %d", ses->server->maxBuf); |
| 569 | GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); | ||
| 570 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); | 566 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); |
| 571 | server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone); | 567 | server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone); |
| 572 | server->timeAdj *= 60; | 568 | server->timeAdj *= 60; |
| @@ -5611,7 +5607,7 @@ QAllEAsRetry: | |||
| 5611 | } | 5607 | } |
| 5612 | 5608 | ||
| 5613 | /* make sure list_len doesn't go past end of SMB */ | 5609 | /* make sure list_len doesn't go past end of SMB */ |
| 5614 | end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr); | 5610 | end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr); |
| 5615 | if ((char *)ea_response_data + list_len > end_of_smb) { | 5611 | if ((char *)ea_response_data + list_len > end_of_smb) { |
| 5616 | cFYI(1, "EA list appears to go beyond SMB"); | 5612 | cFYI(1, "EA list appears to go beyond SMB"); |
| 5617 | rc = -EIO; | 5613 | rc = -EIO; |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 8d4657596301..18d3c7724d6e 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -232,9 +232,8 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
| 232 | static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize) | 232 | static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize) |
| 233 | { | 233 | { |
| 234 | struct smb_t2_rsp *pSMBt; | 234 | struct smb_t2_rsp *pSMBt; |
| 235 | int total_data_size; | ||
| 236 | int data_in_this_rsp; | ||
| 237 | int remaining; | 235 | int remaining; |
| 236 | __u16 total_data_size, data_in_this_rsp; | ||
| 238 | 237 | ||
| 239 | if (pSMB->Command != SMB_COM_TRANSACTION2) | 238 | if (pSMB->Command != SMB_COM_TRANSACTION2) |
| 240 | return 0; | 239 | return 0; |
| @@ -248,8 +247,8 @@ static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize) | |||
| 248 | 247 | ||
| 249 | pSMBt = (struct smb_t2_rsp *)pSMB; | 248 | pSMBt = (struct smb_t2_rsp *)pSMB; |
| 250 | 249 | ||
| 251 | total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount); | 250 | total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); |
| 252 | data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount); | 251 | data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount); |
| 253 | 252 | ||
| 254 | remaining = total_data_size - data_in_this_rsp; | 253 | remaining = total_data_size - data_in_this_rsp; |
| 255 | 254 | ||
| @@ -275,21 +274,18 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) | |||
| 275 | { | 274 | { |
| 276 | struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond; | 275 | struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond; |
| 277 | struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB; | 276 | struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB; |
| 278 | int total_data_size; | ||
| 279 | int total_in_buf; | ||
| 280 | int remaining; | ||
| 281 | int total_in_buf2; | ||
| 282 | char *data_area_of_target; | 277 | char *data_area_of_target; |
| 283 | char *data_area_of_buf2; | 278 | char *data_area_of_buf2; |
| 284 | __u16 byte_count; | 279 | int remaining; |
| 280 | __u16 byte_count, total_data_size, total_in_buf, total_in_buf2; | ||
| 285 | 281 | ||
| 286 | total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount); | 282 | total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); |
| 287 | 283 | ||
| 288 | if (total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) { | 284 | if (total_data_size != |
| 285 | get_unaligned_le16(&pSMB2->t2_rsp.TotalDataCount)) | ||
| 289 | cFYI(1, "total data size of primary and secondary t2 differ"); | 286 | cFYI(1, "total data size of primary and secondary t2 differ"); |
| 290 | } | ||
| 291 | 287 | ||
| 292 | total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount); | 288 | total_in_buf = get_unaligned_le16(&pSMBt->t2_rsp.DataCount); |
| 293 | 289 | ||
| 294 | remaining = total_data_size - total_in_buf; | 290 | remaining = total_data_size - total_in_buf; |
| 295 | 291 | ||
| @@ -299,28 +295,28 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) | |||
| 299 | if (remaining == 0) /* nothing to do, ignore */ | 295 | if (remaining == 0) /* nothing to do, ignore */ |
| 300 | return 0; | 296 | return 0; |
| 301 | 297 | ||
| 302 | total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount); | 298 | total_in_buf2 = get_unaligned_le16(&pSMB2->t2_rsp.DataCount); |
| 303 | if (remaining < total_in_buf2) { | 299 | if (remaining < total_in_buf2) { |
| 304 | cFYI(1, "transact2 2nd response contains too much data"); | 300 | cFYI(1, "transact2 2nd response contains too much data"); |
| 305 | } | 301 | } |
| 306 | 302 | ||
| 307 | /* find end of first SMB data area */ | 303 | /* find end of first SMB data area */ |
| 308 | data_area_of_target = (char *)&pSMBt->hdr.Protocol + | 304 | data_area_of_target = (char *)&pSMBt->hdr.Protocol + |
| 309 | le16_to_cpu(pSMBt->t2_rsp.DataOffset); | 305 | get_unaligned_le16(&pSMBt->t2_rsp.DataOffset); |
| 310 | /* validate target area */ | 306 | /* validate target area */ |
| 311 | 307 | ||
| 312 | data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol + | 308 | data_area_of_buf2 = (char *)&pSMB2->hdr.Protocol + |
| 313 | le16_to_cpu(pSMB2->t2_rsp.DataOffset); | 309 | get_unaligned_le16(&pSMB2->t2_rsp.DataOffset); |
| 314 | 310 | ||
| 315 | data_area_of_target += total_in_buf; | 311 | data_area_of_target += total_in_buf; |
| 316 | 312 | ||
| 317 | /* copy second buffer into end of first buffer */ | 313 | /* copy second buffer into end of first buffer */ |
| 318 | memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2); | 314 | memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2); |
| 319 | total_in_buf += total_in_buf2; | 315 | total_in_buf += total_in_buf2; |
| 320 | pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf); | 316 | put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount); |
| 321 | byte_count = le16_to_cpu(BCC_LE(pTargetSMB)); | 317 | byte_count = get_bcc_le(pTargetSMB); |
| 322 | byte_count += total_in_buf2; | 318 | byte_count += total_in_buf2; |
| 323 | BCC_LE(pTargetSMB) = cpu_to_le16(byte_count); | 319 | put_bcc_le(byte_count, pTargetSMB); |
| 324 | 320 | ||
| 325 | byte_count = pTargetSMB->smb_buf_length; | 321 | byte_count = pTargetSMB->smb_buf_length; |
| 326 | byte_count += total_in_buf2; | 322 | byte_count += total_in_buf2; |
| @@ -334,7 +330,6 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) | |||
| 334 | return 0; /* we are done */ | 330 | return 0; /* we are done */ |
| 335 | } else /* more responses to go */ | 331 | } else /* more responses to go */ |
| 336 | return 1; | 332 | return 1; |
| 337 | |||
| 338 | } | 333 | } |
| 339 | 334 | ||
| 340 | static void | 335 | static void |
| @@ -2937,8 +2932,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
| 2937 | TCONX_RSP *pSMBr; | 2932 | TCONX_RSP *pSMBr; |
| 2938 | unsigned char *bcc_ptr; | 2933 | unsigned char *bcc_ptr; |
| 2939 | int rc = 0; | 2934 | int rc = 0; |
| 2940 | int length, bytes_left; | 2935 | int length; |
| 2941 | __u16 count; | 2936 | __u16 bytes_left, count; |
| 2942 | 2937 | ||
| 2943 | if (ses == NULL) | 2938 | if (ses == NULL) |
| 2944 | return -EIO; | 2939 | return -EIO; |
| @@ -3032,7 +3027,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
| 3032 | tcon->need_reconnect = false; | 3027 | tcon->need_reconnect = false; |
| 3033 | tcon->tid = smb_buffer_response->Tid; | 3028 | tcon->tid = smb_buffer_response->Tid; |
| 3034 | bcc_ptr = pByteArea(smb_buffer_response); | 3029 | bcc_ptr = pByteArea(smb_buffer_response); |
| 3035 | bytes_left = BCC(smb_buffer_response); | 3030 | bytes_left = get_bcc(smb_buffer_response); |
| 3036 | length = strnlen(bcc_ptr, bytes_left - 2); | 3031 | length = strnlen(bcc_ptr, bytes_left - 2); |
| 3037 | if (smb_buffer->Flags2 & SMBFLG2_UNICODE) | 3032 | if (smb_buffer->Flags2 & SMBFLG2_UNICODE) |
| 3038 | is_unicode = true; | 3033 | is_unicode = true; |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index bd2a028af833..d7d65a70678e 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -287,6 +287,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) | |||
| 287 | struct inode *inode = cifs_file->dentry->d_inode; | 287 | struct inode *inode = cifs_file->dentry->d_inode; |
| 288 | struct cifsTconInfo *tcon = tlink_tcon(cifs_file->tlink); | 288 | struct cifsTconInfo *tcon = tlink_tcon(cifs_file->tlink); |
| 289 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | 289 | struct cifsInodeInfo *cifsi = CIFS_I(inode); |
| 290 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
| 290 | struct cifsLockInfo *li, *tmp; | 291 | struct cifsLockInfo *li, *tmp; |
| 291 | 292 | ||
| 292 | spin_lock(&cifs_file_list_lock); | 293 | spin_lock(&cifs_file_list_lock); |
| @@ -302,6 +303,13 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) | |||
| 302 | if (list_empty(&cifsi->openFileList)) { | 303 | if (list_empty(&cifsi->openFileList)) { |
| 303 | cFYI(1, "closing last open instance for inode %p", | 304 | cFYI(1, "closing last open instance for inode %p", |
| 304 | cifs_file->dentry->d_inode); | 305 | cifs_file->dentry->d_inode); |
| 306 | |||
| 307 | /* in strict cache mode we need invalidate mapping on the last | ||
| 308 | close because it may cause a error when we open this file | ||
| 309 | again and get at least level II oplock */ | ||
| 310 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) | ||
| 311 | CIFS_I(inode)->invalid_mapping = true; | ||
| 312 | |||
| 305 | cifs_set_oplock_level(cifsi, 0); | 313 | cifs_set_oplock_level(cifsi, 0); |
| 306 | } | 314 | } |
| 307 | spin_unlock(&cifs_file_list_lock); | 315 | spin_unlock(&cifs_file_list_lock); |
| @@ -1520,27 +1528,47 @@ static int cifs_write_end(struct file *file, struct address_space *mapping, | |||
| 1520 | return rc; | 1528 | return rc; |
| 1521 | } | 1529 | } |
| 1522 | 1530 | ||
| 1523 | int cifs_fsync(struct file *file, int datasync) | 1531 | int cifs_strict_fsync(struct file *file, int datasync) |
| 1524 | { | 1532 | { |
| 1525 | int xid; | 1533 | int xid; |
| 1526 | int rc = 0; | 1534 | int rc = 0; |
| 1527 | struct cifsTconInfo *tcon; | 1535 | struct cifsTconInfo *tcon; |
| 1528 | struct cifsFileInfo *smbfile = file->private_data; | 1536 | struct cifsFileInfo *smbfile = file->private_data; |
| 1529 | struct inode *inode = file->f_path.dentry->d_inode; | 1537 | struct inode *inode = file->f_path.dentry->d_inode; |
| 1538 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
| 1530 | 1539 | ||
| 1531 | xid = GetXid(); | 1540 | xid = GetXid(); |
| 1532 | 1541 | ||
| 1533 | cFYI(1, "Sync file - name: %s datasync: 0x%x", | 1542 | cFYI(1, "Sync file - name: %s datasync: 0x%x", |
| 1534 | file->f_path.dentry->d_name.name, datasync); | 1543 | file->f_path.dentry->d_name.name, datasync); |
| 1535 | 1544 | ||
| 1536 | rc = filemap_write_and_wait(inode->i_mapping); | 1545 | if (!CIFS_I(inode)->clientCanCacheRead) |
| 1537 | if (rc == 0) { | 1546 | cifs_invalidate_mapping(inode); |
| 1538 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
| 1539 | 1547 | ||
| 1540 | tcon = tlink_tcon(smbfile->tlink); | 1548 | tcon = tlink_tcon(smbfile->tlink); |
| 1541 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | 1549 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) |
| 1542 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); | 1550 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); |
| 1543 | } | 1551 | |
| 1552 | FreeXid(xid); | ||
| 1553 | return rc; | ||
| 1554 | } | ||
| 1555 | |||
| 1556 | int cifs_fsync(struct file *file, int datasync) | ||
| 1557 | { | ||
| 1558 | int xid; | ||
| 1559 | int rc = 0; | ||
| 1560 | struct cifsTconInfo *tcon; | ||
| 1561 | struct cifsFileInfo *smbfile = file->private_data; | ||
| 1562 | struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | ||
| 1563 | |||
| 1564 | xid = GetXid(); | ||
| 1565 | |||
| 1566 | cFYI(1, "Sync file - name: %s datasync: 0x%x", | ||
| 1567 | file->f_path.dentry->d_name.name, datasync); | ||
| 1568 | |||
| 1569 | tcon = tlink_tcon(smbfile->tlink); | ||
| 1570 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | ||
| 1571 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); | ||
| 1544 | 1572 | ||
| 1545 | FreeXid(xid); | 1573 | FreeXid(xid); |
| 1546 | return rc; | 1574 | return rc; |
| @@ -1591,42 +1619,42 @@ int cifs_flush(struct file *file, fl_owner_t id) | |||
| 1591 | return rc; | 1619 | return rc; |
| 1592 | } | 1620 | } |
| 1593 | 1621 | ||
| 1594 | ssize_t cifs_user_read(struct file *file, char __user *read_data, | 1622 | static ssize_t |
| 1595 | size_t read_size, loff_t *poffset) | 1623 | cifs_iovec_read(struct file *file, const struct iovec *iov, |
| 1624 | unsigned long nr_segs, loff_t *poffset) | ||
| 1596 | { | 1625 | { |
| 1597 | int rc = -EACCES; | 1626 | int rc; |
| 1598 | unsigned int bytes_read = 0; | 1627 | int xid; |
| 1599 | unsigned int total_read = 0; | 1628 | unsigned int total_read, bytes_read = 0; |
| 1600 | unsigned int current_read_size; | 1629 | size_t len, cur_len; |
| 1630 | int iov_offset = 0; | ||
| 1601 | struct cifs_sb_info *cifs_sb; | 1631 | struct cifs_sb_info *cifs_sb; |
| 1602 | struct cifsTconInfo *pTcon; | 1632 | struct cifsTconInfo *pTcon; |
| 1603 | int xid; | ||
| 1604 | struct cifsFileInfo *open_file; | 1633 | struct cifsFileInfo *open_file; |
| 1605 | char *smb_read_data; | ||
| 1606 | char __user *current_offset; | ||
| 1607 | struct smb_com_read_rsp *pSMBr; | 1634 | struct smb_com_read_rsp *pSMBr; |
| 1635 | char *read_data; | ||
| 1636 | |||
| 1637 | if (!nr_segs) | ||
| 1638 | return 0; | ||
| 1639 | |||
| 1640 | len = iov_length(iov, nr_segs); | ||
| 1641 | if (!len) | ||
| 1642 | return 0; | ||
| 1608 | 1643 | ||
| 1609 | xid = GetXid(); | 1644 | xid = GetXid(); |
| 1610 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 1645 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
| 1611 | 1646 | ||
| 1612 | if (file->private_data == NULL) { | ||
| 1613 | rc = -EBADF; | ||
| 1614 | FreeXid(xid); | ||
| 1615 | return rc; | ||
| 1616 | } | ||
| 1617 | open_file = file->private_data; | 1647 | open_file = file->private_data; |
| 1618 | pTcon = tlink_tcon(open_file->tlink); | 1648 | pTcon = tlink_tcon(open_file->tlink); |
| 1619 | 1649 | ||
| 1620 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) | 1650 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) |
| 1621 | cFYI(1, "attempting read on write only file instance"); | 1651 | cFYI(1, "attempting read on write only file instance"); |
| 1622 | 1652 | ||
| 1623 | for (total_read = 0, current_offset = read_data; | 1653 | for (total_read = 0; total_read < len; total_read += bytes_read) { |
| 1624 | read_size > total_read; | 1654 | cur_len = min_t(const size_t, len - total_read, cifs_sb->rsize); |
| 1625 | total_read += bytes_read, current_offset += bytes_read) { | ||
| 1626 | current_read_size = min_t(const int, read_size - total_read, | ||
| 1627 | cifs_sb->rsize); | ||
| 1628 | rc = -EAGAIN; | 1655 | rc = -EAGAIN; |
| 1629 | smb_read_data = NULL; | 1656 | read_data = NULL; |
| 1657 | |||
| 1630 | while (rc == -EAGAIN) { | 1658 | while (rc == -EAGAIN) { |
| 1631 | int buf_type = CIFS_NO_BUFFER; | 1659 | int buf_type = CIFS_NO_BUFFER; |
| 1632 | if (open_file->invalidHandle) { | 1660 | if (open_file->invalidHandle) { |
| @@ -1634,27 +1662,25 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
| 1634 | if (rc != 0) | 1662 | if (rc != 0) |
| 1635 | break; | 1663 | break; |
| 1636 | } | 1664 | } |
| 1637 | rc = CIFSSMBRead(xid, pTcon, | 1665 | rc = CIFSSMBRead(xid, pTcon, open_file->netfid, |
| 1638 | open_file->netfid, | 1666 | cur_len, *poffset, &bytes_read, |
| 1639 | current_read_size, *poffset, | 1667 | &read_data, &buf_type); |
| 1640 | &bytes_read, &smb_read_data, | 1668 | pSMBr = (struct smb_com_read_rsp *)read_data; |
| 1641 | &buf_type); | 1669 | if (read_data) { |
| 1642 | pSMBr = (struct smb_com_read_rsp *)smb_read_data; | 1670 | char *data_offset = read_data + 4 + |
| 1643 | if (smb_read_data) { | 1671 | le16_to_cpu(pSMBr->DataOffset); |
| 1644 | if (copy_to_user(current_offset, | 1672 | if (memcpy_toiovecend(iov, data_offset, |
| 1645 | smb_read_data + | 1673 | iov_offset, bytes_read)) |
| 1646 | 4 /* RFC1001 length field */ + | ||
| 1647 | le16_to_cpu(pSMBr->DataOffset), | ||
| 1648 | bytes_read)) | ||
| 1649 | rc = -EFAULT; | 1674 | rc = -EFAULT; |
| 1650 | |||
| 1651 | if (buf_type == CIFS_SMALL_BUFFER) | 1675 | if (buf_type == CIFS_SMALL_BUFFER) |
| 1652 | cifs_small_buf_release(smb_read_data); | 1676 | cifs_small_buf_release(read_data); |
| 1653 | else if (buf_type == CIFS_LARGE_BUFFER) | 1677 | else if (buf_type == CIFS_LARGE_BUFFER) |
| 1654 | cifs_buf_release(smb_read_data); | 1678 | cifs_buf_release(read_data); |
| 1655 | smb_read_data = NULL; | 1679 | read_data = NULL; |
| 1680 | iov_offset += bytes_read; | ||
| 1656 | } | 1681 | } |
| 1657 | } | 1682 | } |
| 1683 | |||
| 1658 | if (rc || (bytes_read == 0)) { | 1684 | if (rc || (bytes_read == 0)) { |
| 1659 | if (total_read) { | 1685 | if (total_read) { |
| 1660 | break; | 1686 | break; |
| @@ -1667,13 +1693,57 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
| 1667 | *poffset += bytes_read; | 1693 | *poffset += bytes_read; |
| 1668 | } | 1694 | } |
| 1669 | } | 1695 | } |
| 1696 | |||
| 1670 | FreeXid(xid); | 1697 | FreeXid(xid); |
| 1671 | return total_read; | 1698 | return total_read; |
| 1672 | } | 1699 | } |
| 1673 | 1700 | ||
| 1701 | ssize_t cifs_user_read(struct file *file, char __user *read_data, | ||
| 1702 | size_t read_size, loff_t *poffset) | ||
| 1703 | { | ||
| 1704 | struct iovec iov; | ||
| 1705 | iov.iov_base = read_data; | ||
| 1706 | iov.iov_len = read_size; | ||
| 1707 | |||
| 1708 | return cifs_iovec_read(file, &iov, 1, poffset); | ||
| 1709 | } | ||
| 1710 | |||
| 1711 | static ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, | ||
| 1712 | unsigned long nr_segs, loff_t pos) | ||
| 1713 | { | ||
| 1714 | ssize_t read; | ||
| 1715 | |||
| 1716 | read = cifs_iovec_read(iocb->ki_filp, iov, nr_segs, &pos); | ||
| 1717 | if (read > 0) | ||
| 1718 | iocb->ki_pos = pos; | ||
| 1719 | |||
| 1720 | return read; | ||
| 1721 | } | ||
| 1722 | |||
| 1723 | ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov, | ||
| 1724 | unsigned long nr_segs, loff_t pos) | ||
| 1725 | { | ||
| 1726 | struct inode *inode; | ||
| 1727 | |||
| 1728 | inode = iocb->ki_filp->f_path.dentry->d_inode; | ||
| 1729 | |||
| 1730 | if (CIFS_I(inode)->clientCanCacheRead) | ||
| 1731 | return generic_file_aio_read(iocb, iov, nr_segs, pos); | ||
| 1732 | |||
| 1733 | /* | ||
| 1734 | * In strict cache mode we need to read from the server all the time | ||
| 1735 | * if we don't have level II oplock because the server can delay mtime | ||
| 1736 | * change - so we can't make a decision about inode invalidating. | ||
| 1737 | * And we can also fail with pagereading if there are mandatory locks | ||
| 1738 | * on pages affected by this read but not on the region from pos to | ||
| 1739 | * pos+len-1. | ||
| 1740 | */ | ||
| 1741 | |||
| 1742 | return cifs_user_readv(iocb, iov, nr_segs, pos); | ||
| 1743 | } | ||
| 1674 | 1744 | ||
| 1675 | static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | 1745 | static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, |
| 1676 | loff_t *poffset) | 1746 | loff_t *poffset) |
| 1677 | { | 1747 | { |
| 1678 | int rc = -EACCES; | 1748 | int rc = -EACCES; |
| 1679 | unsigned int bytes_read = 0; | 1749 | unsigned int bytes_read = 0; |
| @@ -1741,6 +1811,21 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
| 1741 | return total_read; | 1811 | return total_read; |
| 1742 | } | 1812 | } |
| 1743 | 1813 | ||
| 1814 | int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma) | ||
| 1815 | { | ||
| 1816 | int rc, xid; | ||
| 1817 | struct inode *inode = file->f_path.dentry->d_inode; | ||
| 1818 | |||
| 1819 | xid = GetXid(); | ||
| 1820 | |||
| 1821 | if (!CIFS_I(inode)->clientCanCacheRead) | ||
| 1822 | cifs_invalidate_mapping(inode); | ||
| 1823 | |||
| 1824 | rc = generic_file_mmap(file, vma); | ||
| 1825 | FreeXid(xid); | ||
| 1826 | return rc; | ||
| 1827 | } | ||
| 1828 | |||
| 1744 | int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) | 1829 | int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) |
| 1745 | { | 1830 | { |
| 1746 | int rc, xid; | 1831 | int rc, xid; |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 6c9ee8014ff0..8852470b4fbb 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -44,13 +44,17 @@ static void cifs_set_ops(struct inode *inode) | |||
| 44 | inode->i_fop = &cifs_file_direct_nobrl_ops; | 44 | inode->i_fop = &cifs_file_direct_nobrl_ops; |
| 45 | else | 45 | else |
| 46 | inode->i_fop = &cifs_file_direct_ops; | 46 | inode->i_fop = &cifs_file_direct_ops; |
| 47 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) { | ||
| 48 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
| 49 | inode->i_fop = &cifs_file_strict_nobrl_ops; | ||
| 50 | else | ||
| 51 | inode->i_fop = &cifs_file_strict_ops; | ||
| 47 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | 52 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) |
| 48 | inode->i_fop = &cifs_file_nobrl_ops; | 53 | inode->i_fop = &cifs_file_nobrl_ops; |
| 49 | else { /* not direct, send byte range locks */ | 54 | else { /* not direct, send byte range locks */ |
| 50 | inode->i_fop = &cifs_file_ops; | 55 | inode->i_fop = &cifs_file_ops; |
| 51 | } | 56 | } |
| 52 | 57 | ||
| 53 | |||
| 54 | /* check if server can support readpages */ | 58 | /* check if server can support readpages */ |
| 55 | if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf < | 59 | if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf < |
| 56 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) | 60 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) |
| @@ -1679,7 +1683,7 @@ cifs_inode_needs_reval(struct inode *inode) | |||
| 1679 | /* | 1683 | /* |
| 1680 | * Zap the cache. Called when invalid_mapping flag is set. | 1684 | * Zap the cache. Called when invalid_mapping flag is set. |
| 1681 | */ | 1685 | */ |
| 1682 | static void | 1686 | void |
| 1683 | cifs_invalidate_mapping(struct inode *inode) | 1687 | cifs_invalidate_mapping(struct inode *inode) |
| 1684 | { | 1688 | { |
| 1685 | int rc; | 1689 | int rc; |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 09bfcf08a90f..a09e077ba925 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
| @@ -637,77 +637,6 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length) | |||
| 637 | return; | 637 | return; |
| 638 | } | 638 | } |
| 639 | 639 | ||
| 640 | /* Convert 16 bit Unicode pathname to wire format from string in current code | ||
| 641 | page. Conversion may involve remapping up the seven characters that are | ||
| 642 | only legal in POSIX-like OS (if they are present in the string). Path | ||
| 643 | names are little endian 16 bit Unicode on the wire */ | ||
| 644 | int | ||
| 645 | cifsConvertToUCS(__le16 *target, const char *source, int maxlen, | ||
| 646 | const struct nls_table *cp, int mapChars) | ||
| 647 | { | ||
| 648 | int i, j, charlen; | ||
| 649 | int len_remaining = maxlen; | ||
| 650 | char src_char; | ||
| 651 | __u16 temp; | ||
| 652 | |||
| 653 | if (!mapChars) | ||
| 654 | return cifs_strtoUCS(target, source, PATH_MAX, cp); | ||
| 655 | |||
| 656 | for (i = 0, j = 0; i < maxlen; j++) { | ||
| 657 | src_char = source[i]; | ||
| 658 | switch (src_char) { | ||
| 659 | case 0: | ||
| 660 | target[j] = 0; | ||
| 661 | goto ctoUCS_out; | ||
| 662 | case ':': | ||
| 663 | target[j] = cpu_to_le16(UNI_COLON); | ||
| 664 | break; | ||
| 665 | case '*': | ||
| 666 | target[j] = cpu_to_le16(UNI_ASTERIK); | ||
| 667 | break; | ||
| 668 | case '?': | ||
| 669 | target[j] = cpu_to_le16(UNI_QUESTION); | ||
| 670 | break; | ||
| 671 | case '<': | ||
| 672 | target[j] = cpu_to_le16(UNI_LESSTHAN); | ||
| 673 | break; | ||
| 674 | case '>': | ||
| 675 | target[j] = cpu_to_le16(UNI_GRTRTHAN); | ||
| 676 | break; | ||
| 677 | case '|': | ||
| 678 | target[j] = cpu_to_le16(UNI_PIPE); | ||
| 679 | break; | ||
| 680 | /* BB We can not handle remapping slash until | ||
| 681 | all the calls to build_path_from_dentry | ||
| 682 | are modified, as they use slash as separator BB */ | ||
| 683 | /* case '\\': | ||
| 684 | target[j] = cpu_to_le16(UNI_SLASH); | ||
| 685 | break;*/ | ||
| 686 | default: | ||
| 687 | charlen = cp->char2uni(source+i, | ||
| 688 | len_remaining, &temp); | ||
| 689 | /* if no match, use question mark, which | ||
| 690 | at least in some cases servers as wild card */ | ||
| 691 | if (charlen < 1) { | ||
| 692 | target[j] = cpu_to_le16(0x003f); | ||
| 693 | charlen = 1; | ||
| 694 | } else | ||
| 695 | target[j] = cpu_to_le16(temp); | ||
| 696 | len_remaining -= charlen; | ||
| 697 | /* character may take more than one byte in the | ||
| 698 | the source string, but will take exactly two | ||
| 699 | bytes in the target string */ | ||
| 700 | i += charlen; | ||
| 701 | continue; | ||
| 702 | } | ||
| 703 | i++; /* move to next char in source string */ | ||
| 704 | len_remaining--; | ||
| 705 | } | ||
| 706 | |||
| 707 | ctoUCS_out: | ||
| 708 | return i; | ||
| 709 | } | ||
| 710 | |||
| 711 | void | 640 | void |
| 712 | cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb) | 641 | cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb) |
| 713 | { | 642 | { |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 6783ce6cdc89..8d9189f64477 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
| @@ -916,14 +916,14 @@ unsigned int | |||
| 916 | smbCalcSize(struct smb_hdr *ptr) | 916 | smbCalcSize(struct smb_hdr *ptr) |
| 917 | { | 917 | { |
| 918 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + | 918 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + |
| 919 | 2 /* size of the bcc field */ + BCC(ptr)); | 919 | 2 /* size of the bcc field */ + get_bcc(ptr)); |
| 920 | } | 920 | } |
| 921 | 921 | ||
| 922 | unsigned int | 922 | unsigned int |
| 923 | smbCalcSize_LE(struct smb_hdr *ptr) | 923 | smbCalcSize_LE(struct smb_hdr *ptr) |
| 924 | { | 924 | { |
| 925 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + | 925 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + |
| 926 | 2 /* size of the bcc field */ + le16_to_cpu(BCC_LE(ptr))); | 926 | 2 /* size of the bcc field */ + get_bcc_le(ptr)); |
| 927 | } | 927 | } |
| 928 | 928 | ||
| 929 | /* The following are taken from fs/ntfs/util.c */ | 929 | /* The following are taken from fs/ntfs/util.c */ |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 1cffd82c4f13..1adc9625a344 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
| @@ -277,7 +277,7 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses, | |||
| 277 | } | 277 | } |
| 278 | 278 | ||
| 279 | static void | 279 | static void |
| 280 | decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses, | 280 | decode_unicode_ssetup(char **pbcc_area, __u16 bleft, struct cifsSesInfo *ses, |
| 281 | const struct nls_table *nls_cp) | 281 | const struct nls_table *nls_cp) |
| 282 | { | 282 | { |
| 283 | int len; | 283 | int len; |
| @@ -323,7 +323,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses, | |||
| 323 | return; | 323 | return; |
| 324 | } | 324 | } |
| 325 | 325 | ||
| 326 | static int decode_ascii_ssetup(char **pbcc_area, int bleft, | 326 | static int decode_ascii_ssetup(char **pbcc_area, __u16 bleft, |
| 327 | struct cifsSesInfo *ses, | 327 | struct cifsSesInfo *ses, |
| 328 | const struct nls_table *nls_cp) | 328 | const struct nls_table *nls_cp) |
| 329 | { | 329 | { |
| @@ -575,12 +575,11 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
| 575 | char *str_area; | 575 | char *str_area; |
| 576 | SESSION_SETUP_ANDX *pSMB; | 576 | SESSION_SETUP_ANDX *pSMB; |
| 577 | __u32 capabilities; | 577 | __u32 capabilities; |
| 578 | int count; | 578 | __u16 count; |
| 579 | int resp_buf_type; | 579 | int resp_buf_type; |
| 580 | struct kvec iov[3]; | 580 | struct kvec iov[3]; |
| 581 | enum securityEnum type; | 581 | enum securityEnum type; |
| 582 | __u16 action; | 582 | __u16 action, bytes_remaining; |
| 583 | int bytes_remaining; | ||
| 584 | struct key *spnego_key = NULL; | 583 | struct key *spnego_key = NULL; |
| 585 | __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ | 584 | __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ |
| 586 | u16 blob_len; | 585 | u16 blob_len; |
| @@ -876,7 +875,7 @@ ssetup_ntlmssp_authenticate: | |||
| 876 | count = iov[1].iov_len + iov[2].iov_len; | 875 | count = iov[1].iov_len + iov[2].iov_len; |
| 877 | smb_buf->smb_buf_length += count; | 876 | smb_buf->smb_buf_length += count; |
| 878 | 877 | ||
| 879 | BCC_LE(smb_buf) = cpu_to_le16(count); | 878 | put_bcc_le(count, smb_buf); |
| 880 | 879 | ||
| 881 | rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type, | 880 | rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type, |
| 882 | CIFS_LOG_ERROR); | 881 | CIFS_LOG_ERROR); |
| @@ -910,7 +909,7 @@ ssetup_ntlmssp_authenticate: | |||
| 910 | cFYI(1, "UID = %d ", ses->Suid); | 909 | cFYI(1, "UID = %d ", ses->Suid); |
| 911 | /* response can have either 3 or 4 word count - Samba sends 3 */ | 910 | /* response can have either 3 or 4 word count - Samba sends 3 */ |
| 912 | /* and lanman response is 3 */ | 911 | /* and lanman response is 3 */ |
| 913 | bytes_remaining = BCC(smb_buf); | 912 | bytes_remaining = get_bcc(smb_buf); |
| 914 | bcc_ptr = pByteArea(smb_buf); | 913 | bcc_ptr = pByteArea(smb_buf); |
| 915 | 914 | ||
| 916 | if (smb_buf->WordCount == 4) { | 915 | if (smb_buf->WordCount == 4) { |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index c8e2808cd5e6..c1ccca1a933f 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
| @@ -484,7 +484,7 @@ send_nt_cancel(struct TCP_Server_Info *server, struct smb_hdr *in_buf, | |||
| 484 | in_buf->smb_buf_length = sizeof(struct smb_hdr) - 4 + 2; | 484 | in_buf->smb_buf_length = sizeof(struct smb_hdr) - 4 + 2; |
| 485 | in_buf->Command = SMB_COM_NT_CANCEL; | 485 | in_buf->Command = SMB_COM_NT_CANCEL; |
| 486 | in_buf->WordCount = 0; | 486 | in_buf->WordCount = 0; |
| 487 | BCC_LE(in_buf) = 0; | 487 | put_bcc_le(0, in_buf); |
| 488 | 488 | ||
| 489 | mutex_lock(&server->srv_mutex); | 489 | mutex_lock(&server->srv_mutex); |
| 490 | rc = cifs_sign_smb(in_buf, server, &mid->sequence_number); | 490 | rc = cifs_sign_smb(in_buf, server, &mid->sequence_number); |
| @@ -632,8 +632,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
| 632 | if (receive_len >= sizeof(struct smb_hdr) - 4 | 632 | if (receive_len >= sizeof(struct smb_hdr) - 4 |
| 633 | /* do not count RFC1001 header */ + | 633 | /* do not count RFC1001 header */ + |
| 634 | (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) | 634 | (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) |
| 635 | BCC(midQ->resp_buf) = | 635 | put_bcc(get_bcc_le(midQ->resp_buf), midQ->resp_buf); |
| 636 | le16_to_cpu(BCC_LE(midQ->resp_buf)); | ||
| 637 | if ((flags & CIFS_NO_RESP) == 0) | 636 | if ((flags & CIFS_NO_RESP) == 0) |
| 638 | midQ->resp_buf = NULL; /* mark it so buf will | 637 | midQ->resp_buf = NULL; /* mark it so buf will |
| 639 | not be freed by | 638 | not be freed by |
| @@ -776,7 +775,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
| 776 | if (receive_len >= sizeof(struct smb_hdr) - 4 | 775 | if (receive_len >= sizeof(struct smb_hdr) - 4 |
| 777 | /* do not count RFC1001 header */ + | 776 | /* do not count RFC1001 header */ + |
| 778 | (2 * out_buf->WordCount) + 2 /* bcc */ ) | 777 | (2 * out_buf->WordCount) + 2 /* bcc */ ) |
| 779 | BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); | 778 | put_bcc(get_bcc_le(midQ->resp_buf), midQ->resp_buf); |
| 780 | } else { | 779 | } else { |
| 781 | rc = -EIO; | 780 | rc = -EIO; |
| 782 | cERROR(1, "Bad MID state?"); | 781 | cERROR(1, "Bad MID state?"); |
| @@ -977,7 +976,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
| 977 | if (receive_len >= sizeof(struct smb_hdr) - 4 | 976 | if (receive_len >= sizeof(struct smb_hdr) - 4 |
| 978 | /* do not count RFC1001 header */ + | 977 | /* do not count RFC1001 header */ + |
| 979 | (2 * out_buf->WordCount) + 2 /* bcc */ ) | 978 | (2 * out_buf->WordCount) + 2 /* bcc */ ) |
| 980 | BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); | 979 | put_bcc(get_bcc_le(out_buf), out_buf); |
| 981 | 980 | ||
| 982 | out: | 981 | out: |
| 983 | delete_mid(midQ); | 982 | delete_mid(midQ); |
