aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-21 16:44:07 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-21 16:44:07 -0500
commit9093ba53b7f26dbb5210de1157769e59e34bbe23 (patch)
tree98b6fac2f483740828a58b8bbacaf9016d8e9278 /fs
parentebe0d805071c318ebbc3b5857f8f4f94214c1a52 (diff)
parent99d86c8f1b7101d7c55dbf644b32bb1f0d7eb303 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: cifs: fix up CIFSSMBEcho for unaligned access cifs: fix unaligned accesses in cifsConvertToUCS cifs: clean up unaligned accesses in cifs_unicode.c cifs: fix unaligned access in check2ndT2 and coalesce_t2 cifs: clean up unaligned accesses in validate_t2 cifs: use get/put_unaligned functions to access ByteCount cifs: move time field in cifsInodeInfo cifs: TCP_Server_Info diet CIFS: Implement cifs_strict_readv (try #4) CIFS: Implement cifs_file_strict_mmap (try #2) CIFS: Implement cifs_strict_fsync CIFS: Make cifsFileInfo_put work with strict cache mode
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifs_fs_sb.h1
-rw-r--r--fs/cifs/cifs_unicode.c127
-rw-r--r--fs/cifs/cifsfs.c38
-rw-r--r--fs/cifs/cifsfs.h13
-rw-r--r--fs/cifs/cifsglob.h36
-rw-r--r--fs/cifs/cifspdu.h47
-rw-r--r--fs/cifs/cifssmb.c60
-rw-r--r--fs/cifs/connect.c43
-rw-r--r--fs/cifs/file.c175
-rw-r--r--fs/cifs/inode.c8
-rw-r--r--fs/cifs/misc.c71
-rw-r--r--fs/cifs/netmisc.c4
-rw-r--r--fs/cifs/sess.c13
-rw-r--r--fs/cifs/transport.c9
14 files changed, 405 insertions, 240 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
44struct cifs_sb_info { 45struct 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 */
71static int 75static int
72cifs_mapchar(char *target, const __le16 src_char, const struct nls_table *cp, 76cifs_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
111cp_convert: 115cp_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 */
266int
267cifsConvertToUCS(__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
332ctoUCS_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
736const 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
736const struct file_operations cifs_file_direct_ops = { 755const 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
754const struct file_operations cifs_file_nobrl_ops = { 774const 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
792const 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
772const struct file_operations cifs_file_direct_nobrl_ops = { 810const 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 *);
62extern int cifs_revalidate_file(struct file *filp); 62extern int cifs_revalidate_file(struct file *filp);
63extern int cifs_revalidate_dentry(struct dentry *); 63extern int cifs_revalidate_dentry(struct dentry *);
64extern void cifs_invalidate_mapping(struct inode *inode);
64extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); 65extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
65extern int cifs_setattr(struct dentry *, struct iattr *); 66extern 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 */
73extern const struct file_operations cifs_file_ops; 74extern const struct file_operations cifs_file_ops;
74extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */ 75extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */
75extern const struct file_operations cifs_file_nobrl_ops; 76extern const struct file_operations cifs_file_strict_ops; /* if strictio mnt */
76extern const struct file_operations cifs_file_direct_nobrl_ops; /* no brlocks */ 77extern const struct file_operations cifs_file_nobrl_ops; /* no brlocks */
78extern const struct file_operations cifs_file_direct_nobrl_ops;
79extern const struct file_operations cifs_file_strict_nobrl_ops;
77extern int cifs_open(struct inode *inode, struct file *file); 80extern int cifs_open(struct inode *inode, struct file *file);
78extern int cifs_close(struct inode *inode, struct file *file); 81extern int cifs_close(struct inode *inode, struct file *file);
79extern int cifs_closedir(struct inode *inode, struct file *file); 82extern int cifs_closedir(struct inode *inode, struct file *file);
80extern ssize_t cifs_user_read(struct file *file, char __user *read_data, 83extern 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);
85extern ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov,
86 unsigned long nr_segs, loff_t pos);
82extern ssize_t cifs_user_write(struct file *file, const char __user *write_data, 87extern 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);
84extern int cifs_lock(struct file *, int, struct file_lock *); 89extern int cifs_lock(struct file *, int, struct file_lock *);
85extern int cifs_fsync(struct file *, int); 90extern int cifs_fsync(struct file *, int);
91extern int cifs_strict_fsync(struct file *, int);
86extern int cifs_flush(struct file *, fl_owner_t id); 92extern int cifs_flush(struct file *, fl_owner_t id);
87extern int cifs_file_mmap(struct file * , struct vm_area_struct *); 93extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
94extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *);
88extern const struct file_operations cifs_dir_ops; 95extern const struct file_operations cifs_dir_ops;
89extern int cifs_dir_open(struct inode *inode, struct file *file); 96extern int cifs_dir_open(struct inode *inode, struct file *file);
90extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); 97extern 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 */
439static inline __u16
440get_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 */
448static inline __u16
449get_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 */
457static inline void
458put_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 */
466static inline void
467put_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..3106f5e5c633 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
332static int validate_t2(struct smb_t2_rsp *pSMB) 332static 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; 357vt2_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
365int 363int
366CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) 364CIFSSMBNegotiate(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;
@@ -737,9 +733,9 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
737 733
738 /* set up echo request */ 734 /* set up echo request */
739 smb->hdr.Tid = cpu_to_le16(0xffff); 735 smb->hdr.Tid = cpu_to_le16(0xffff);
740 smb->hdr.WordCount = cpu_to_le16(1); 736 smb->hdr.WordCount = 1;
741 smb->EchoCount = cpu_to_le16(1); 737 put_unaligned_le16(1, &smb->EchoCount);
742 smb->ByteCount = cpu_to_le16(1); 738 put_bcc_le(1, &smb->hdr);
743 smb->Data[0] = 'a'; 739 smb->Data[0] = 'a';
744 smb->hdr.smb_buf_length += 3; 740 smb->hdr.smb_buf_length += 3;
745 741
@@ -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)
232static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize) 232static 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
340static void 335static 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
1523int cifs_fsync(struct file *file, int datasync) 1531int 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
1556int 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
1594ssize_t cifs_user_read(struct file *file, char __user *read_data, 1622static ssize_t
1595 size_t read_size, loff_t *poffset) 1623cifs_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
1701ssize_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
1711static 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
1723ssize_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
1675static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, 1745static 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
1814int 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
1744int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) 1829int 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 */
1682static void 1686void
1683cifs_invalidate_mapping(struct inode *inode) 1687cifs_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 */
644int
645cifsConvertToUCS(__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
707ctoUCS_out:
708 return i;
709}
710
711void 640void
712cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb) 641cifs_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
916smbCalcSize(struct smb_hdr *ptr) 916smbCalcSize(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
922unsigned int 922unsigned int
923smbCalcSize_LE(struct smb_hdr *ptr) 923smbCalcSize_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
279static void 279static void
280decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses, 280decode_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
326static int decode_ascii_ssetup(char **pbcc_area, int bleft, 326static 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
982out: 981out:
983 delete_mid(midQ); 982 delete_mid(midQ);