aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/CHANGES9
-rw-r--r--fs/cifs/README2
-rw-r--r--fs/cifs/asn1.c2
-rw-r--r--fs/cifs/cifs_dfs_ref.c6
-rw-r--r--fs/cifs/cifs_fs_sb.h3
-rw-r--r--fs/cifs/cifs_spnego.c1
-rw-r--r--fs/cifs/cifs_unicode.c1
-rw-r--r--fs/cifs/cifsacl.c1
-rw-r--r--fs/cifs/cifsencrypt.c1
-rw-r--r--fs/cifs/cifsfs.c17
-rw-r--r--fs/cifs/cifsfs.h5
-rw-r--r--fs/cifs/cifsglob.h8
-rw-r--r--fs/cifs/cifspdu.h8
-rw-r--r--fs/cifs/cifsproto.h13
-rw-r--r--fs/cifs/cifssmb.c532
-rw-r--r--fs/cifs/connect.c52
-rw-r--r--fs/cifs/dir.c5
-rw-r--r--fs/cifs/dns_resolve.c1
-rw-r--r--fs/cifs/export.c2
-rw-r--r--fs/cifs/file.c46
-rw-r--r--fs/cifs/inode.c338
-rw-r--r--fs/cifs/link.c1
-rw-r--r--fs/cifs/misc.c2
-rw-r--r--fs/cifs/readdir.c9
-rw-r--r--fs/cifs/sess.c12
-rw-r--r--fs/cifs/smbdes.c2
-rw-r--r--fs/cifs/smbencrypt.c1
-rw-r--r--fs/cifs/transport.c1
-rw-r--r--fs/cifs/xattr.c9
29 files changed, 673 insertions, 417 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 094ea65afc85..bc0025cdd1c9 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,8 @@
1Version 1.62
2------------
3Add sockopt=TCP_NODELAY mount option. EA (xattr) routines hardened
4to more strictly handle corrupt frames.
5
1Version 1.61 6Version 1.61
2------------ 7------------
3Fix append problem to Samba servers (files opened with O_APPEND could 8Fix append problem to Samba servers (files opened with O_APPEND could
@@ -5,7 +10,9 @@ have duplicated data). Fix oops in cifs_lookup. Workaround problem
5mounting to OS/400 Netserve. Fix oops in cifs_get_tcp_session. 10mounting to OS/400 Netserve. Fix oops in cifs_get_tcp_session.
6Disable use of server inode numbers when server only 11Disable use of server inode numbers when server only
7partially supports them (e.g. for one server querying inode numbers on 12partially supports them (e.g. for one server querying inode numbers on
8FindFirst fails but QPathInfo queries works). 13FindFirst fails but QPathInfo queries works). Fix oops with dfs in
14cifs_put_smb_ses. Fix mmap to work on directio mounts (needed
15for OpenOffice when on forcedirectio mount e.g.)
9 16
10Version 1.60 17Version 1.60
11------------- 18-------------
diff --git a/fs/cifs/README b/fs/cifs/README
index 79c1a93400be..a727b7cb075f 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -423,7 +423,7 @@ A partial list of the supported mount options follows:
423 source name to use to represent the client netbios machine 423 source name to use to represent the client netbios machine
424 name when doing the RFC1001 netbios session initialize. 424 name when doing the RFC1001 netbios session initialize.
425 direct Do not do inode data caching on files opened on this mount. 425 direct Do not do inode data caching on files opened on this mount.
426 This precludes mmaping files on this mount. In some cases 426 This precludes mmapping files on this mount. In some cases
427 with fast networks and little or no caching benefits on the 427 with fast networks and little or no caching benefits on the
428 client (e.g. when the application is doing large sequential 428 client (e.g. when the application is doing large sequential
429 reads bigger than page size without rereading the same data) 429 reads bigger than page size without rereading the same data)
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index 20692fbfdb24..a20bea598933 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -136,7 +136,7 @@ asn1_enum_decode(struct asn1_ctx *ctx, __le32 *val)
136 return 0; 136 return 0;
137 } 137 }
138 138
139 ch = *(ctx->pointer)++; /* ch has 0xa, ptr points to lenght octet */ 139 ch = *(ctx->pointer)++; /* ch has 0xa, ptr points to length octet */
140 if ((ch) == ASN1_ENUM) /* if ch value is ENUM, 0xa */ 140 if ((ch) == ASN1_ENUM) /* if ch value is ENUM, 0xa */
141 *val = *(++(ctx->pointer)); /* value has enum value */ 141 *val = *(++(ctx->pointer)); /* value has enum value */
142 else 142 else
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index fea9e898c4ba..78e4d2a3a68b 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -15,6 +15,7 @@
15#include <linux/dcache.h> 15#include <linux/dcache.h>
16#include <linux/mount.h> 16#include <linux/mount.h>
17#include <linux/namei.h> 17#include <linux/namei.h>
18#include <linux/slab.h>
18#include <linux/vfs.h> 19#include <linux/vfs.h>
19#include <linux/fs.h> 20#include <linux/fs.h>
20#include "cifsglob.h" 21#include "cifsglob.h"
@@ -54,7 +55,7 @@ void cifs_dfs_release_automount_timer(void)
54 * Extracts sharename form full UNC. 55 * Extracts sharename form full UNC.
55 * i.e. strips from UNC trailing path that is not part of share 56 * i.e. strips from UNC trailing path that is not part of share
56 * name and fixup missing '\' in the begining of DFS node refferal 57 * name and fixup missing '\' in the begining of DFS node refferal
57 * if neccessary. 58 * if necessary.
58 * Returns pointer to share name on success or ERR_PTR on error. 59 * Returns pointer to share name on success or ERR_PTR on error.
59 * Caller is responsible for freeing returned string. 60 * Caller is responsible for freeing returned string.
60 */ 61 */
@@ -269,7 +270,7 @@ static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd,
269 int err; 270 int err;
270 271
271 mntget(newmnt); 272 mntget(newmnt);
272 err = do_add_mount(newmnt, &nd->path, nd->path.mnt->mnt_flags, mntlist); 273 err = do_add_mount(newmnt, &nd->path, nd->path.mnt->mnt_flags | MNT_SHRINKABLE, mntlist);
273 switch (err) { 274 switch (err) {
274 case 0: 275 case 0:
275 path_put(&nd->path); 276 path_put(&nd->path);
@@ -371,7 +372,6 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
371 if (IS_ERR(mnt)) 372 if (IS_ERR(mnt))
372 goto out_err; 373 goto out_err;
373 374
374 nd->path.mnt->mnt_flags |= MNT_SHRINKABLE;
375 rc = add_mount_helper(mnt, nd, &cifs_dfs_automount_list); 375 rc = add_mount_helper(mnt, nd, &cifs_dfs_automount_list);
376 376
377out: 377out:
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 4797787c6a44..246a167cb913 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -18,6 +18,8 @@
18#ifndef _CIFS_FS_SB_H 18#ifndef _CIFS_FS_SB_H
19#define _CIFS_FS_SB_H 19#define _CIFS_FS_SB_H
20 20
21#include <linux/backing-dev.h>
22
21#define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */ 23#define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */
22#define CIFS_MOUNT_SET_UID 2 /* set current's euid in create etc. */ 24#define CIFS_MOUNT_SET_UID 2 /* set current's euid in create etc. */
23#define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */ 25#define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */
@@ -50,5 +52,6 @@ struct cifs_sb_info {
50#ifdef CONFIG_CIFS_DFS_UPCALL 52#ifdef CONFIG_CIFS_DFS_UPCALL
51 char *mountdata; /* mount options received at mount time */ 53 char *mountdata; /* mount options received at mount time */
52#endif 54#endif
55 struct backing_dev_info bdi;
53}; 56};
54#endif /* _CIFS_FS_SB_H */ 57#endif /* _CIFS_FS_SB_H */
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
index 8ec7736ce954..310d12f69a92 100644
--- a/fs/cifs/cifs_spnego.c
+++ b/fs/cifs/cifs_spnego.c
@@ -20,6 +20,7 @@
20 */ 20 */
21 21
22#include <linux/list.h> 22#include <linux/list.h>
23#include <linux/slab.h>
23#include <linux/string.h> 24#include <linux/string.h>
24#include <keys/user-type.h> 25#include <keys/user-type.h>
25#include <linux/key-type.h> 26#include <linux/key-type.h>
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 714a542cbafc..d07676bd76d2 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -19,6 +19,7 @@
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */ 20 */
21#include <linux/fs.h> 21#include <linux/fs.h>
22#include <linux/slab.h>
22#include "cifs_unicode.h" 23#include "cifs_unicode.h"
23#include "cifs_uniupr.h" 24#include "cifs_uniupr.h"
24#include "cifspdu.h" 25#include "cifspdu.h"
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 7dfe0842a6f6..9b716d044bbd 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -22,6 +22,7 @@
22 */ 22 */
23 23
24#include <linux/fs.h> 24#include <linux/fs.h>
25#include <linux/slab.h>
25#include "cifspdu.h" 26#include "cifspdu.h"
26#include "cifsglob.h" 27#include "cifsglob.h"
27#include "cifsacl.h" 28#include "cifsacl.h"
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 7efe1745494d..fbe986430d0c 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -20,6 +20,7 @@
20 */ 20 */
21 21
22#include <linux/fs.h> 22#include <linux/fs.h>
23#include <linux/slab.h>
23#include "cifspdu.h" 24#include "cifspdu.h"
24#include "cifsglob.h" 25#include "cifsglob.h"
25#include "cifs_debug.h" 26#include "cifs_debug.h"
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 29f1da761bbf..ad235d604a0b 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -103,6 +103,12 @@ cifs_read_super(struct super_block *sb, void *data,
103 if (cifs_sb == NULL) 103 if (cifs_sb == NULL)
104 return -ENOMEM; 104 return -ENOMEM;
105 105
106 rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
107 if (rc) {
108 kfree(cifs_sb);
109 return rc;
110 }
111
106#ifdef CONFIG_CIFS_DFS_UPCALL 112#ifdef CONFIG_CIFS_DFS_UPCALL
107 /* copy mount params to sb for use in submounts */ 113 /* copy mount params to sb for use in submounts */
108 /* BB: should we move this after the mount so we 114 /* BB: should we move this after the mount so we
@@ -115,6 +121,7 @@ cifs_read_super(struct super_block *sb, void *data,
115 int len = strlen(data); 121 int len = strlen(data);
116 cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL); 122 cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL);
117 if (cifs_sb->mountdata == NULL) { 123 if (cifs_sb->mountdata == NULL) {
124 bdi_destroy(&cifs_sb->bdi);
118 kfree(sb->s_fs_info); 125 kfree(sb->s_fs_info);
119 sb->s_fs_info = NULL; 126 sb->s_fs_info = NULL;
120 return -ENOMEM; 127 return -ENOMEM;
@@ -135,6 +142,7 @@ cifs_read_super(struct super_block *sb, void *data,
135 142
136 sb->s_magic = CIFS_MAGIC_NUMBER; 143 sb->s_magic = CIFS_MAGIC_NUMBER;
137 sb->s_op = &cifs_super_ops; 144 sb->s_op = &cifs_super_ops;
145 sb->s_bdi = &cifs_sb->bdi;
138/* if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512) 146/* if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
139 sb->s_blocksize = 147 sb->s_blocksize =
140 cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */ 148 cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
@@ -183,6 +191,7 @@ out_mount_failed:
183 } 191 }
184#endif 192#endif
185 unload_nls(cifs_sb->local_nls); 193 unload_nls(cifs_sb->local_nls);
194 bdi_destroy(&cifs_sb->bdi);
186 kfree(cifs_sb); 195 kfree(cifs_sb);
187 } 196 }
188 return rc; 197 return rc;
@@ -214,6 +223,7 @@ cifs_put_super(struct super_block *sb)
214#endif 223#endif
215 224
216 unload_nls(cifs_sb->local_nls); 225 unload_nls(cifs_sb->local_nls);
226 bdi_destroy(&cifs_sb->bdi);
217 kfree(cifs_sb); 227 kfree(cifs_sb);
218 228
219 unlock_kernel(); 229 unlock_kernel();
@@ -312,6 +322,7 @@ cifs_alloc_inode(struct super_block *sb)
312 cifs_inode->clientCanCacheRead = false; 322 cifs_inode->clientCanCacheRead = false;
313 cifs_inode->clientCanCacheAll = false; 323 cifs_inode->clientCanCacheAll = false;
314 cifs_inode->delete_pending = false; 324 cifs_inode->delete_pending = false;
325 cifs_inode->invalid_mapping = false;
315 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ 326 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
316 cifs_inode->server_eof = 0; 327 cifs_inode->server_eof = 0;
317 328
@@ -638,7 +649,7 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
638 setting the revalidate time to zero */ 649 setting the revalidate time to zero */
639 CIFS_I(file->f_path.dentry->d_inode)->time = 0; 650 CIFS_I(file->f_path.dentry->d_inode)->time = 0;
640 651
641 retval = cifs_revalidate(file->f_path.dentry); 652 retval = cifs_revalidate_file(file);
642 if (retval < 0) 653 if (retval < 0)
643 return (loff_t)retval; 654 return (loff_t)retval;
644 } 655 }
@@ -758,7 +769,7 @@ const struct file_operations cifs_file_ops = {
758}; 769};
759 770
760const struct file_operations cifs_file_direct_ops = { 771const struct file_operations cifs_file_direct_ops = {
761 /* no mmap, no aio, no readv - 772 /* no aio, no readv -
762 BB reevaluate whether they can be done with directio, no cache */ 773 BB reevaluate whether they can be done with directio, no cache */
763 .read = cifs_user_read, 774 .read = cifs_user_read,
764 .write = cifs_user_write, 775 .write = cifs_user_write,
@@ -767,6 +778,7 @@ const struct file_operations cifs_file_direct_ops = {
767 .lock = cifs_lock, 778 .lock = cifs_lock,
768 .fsync = cifs_fsync, 779 .fsync = cifs_fsync,
769 .flush = cifs_flush, 780 .flush = cifs_flush,
781 .mmap = cifs_file_mmap,
770 .splice_read = generic_file_splice_read, 782 .splice_read = generic_file_splice_read,
771#ifdef CONFIG_CIFS_POSIX 783#ifdef CONFIG_CIFS_POSIX
772 .unlocked_ioctl = cifs_ioctl, 784 .unlocked_ioctl = cifs_ioctl,
@@ -806,6 +818,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
806 .release = cifs_close, 818 .release = cifs_close,
807 .fsync = cifs_fsync, 819 .fsync = cifs_fsync,
808 .flush = cifs_flush, 820 .flush = cifs_flush,
821 .mmap = cifs_file_mmap,
809 .splice_read = generic_file_splice_read, 822 .splice_read = generic_file_splice_read,
810#ifdef CONFIG_CIFS_POSIX 823#ifdef CONFIG_CIFS_POSIX
811 .unlocked_ioctl = cifs_ioctl, 824 .unlocked_ioctl = cifs_ioctl,
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index ac2b24c192f8..7aa57ecdc437 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -61,7 +61,8 @@ extern int cifs_mkdir(struct inode *, struct dentry *, int);
61extern int cifs_rmdir(struct inode *, struct dentry *); 61extern int cifs_rmdir(struct inode *, struct dentry *);
62extern int cifs_rename(struct inode *, struct dentry *, struct inode *, 62extern int cifs_rename(struct inode *, struct dentry *, struct inode *,
63 struct dentry *); 63 struct dentry *);
64extern int cifs_revalidate(struct dentry *); 64extern int cifs_revalidate_file(struct file *filp);
65extern int cifs_revalidate_dentry(struct dentry *);
65extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); 66extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
66extern int cifs_setattr(struct dentry *, struct iattr *); 67extern int cifs_setattr(struct dentry *, struct iattr *);
67 68
@@ -113,5 +114,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
113extern const struct export_operations cifs_export_ops; 114extern const struct export_operations cifs_export_ops;
114#endif /* EXPERIMENTAL */ 115#endif /* EXPERIMENTAL */
115 116
116#define CIFS_VERSION "1.61" 117#define CIFS_VERSION "1.62"
117#endif /* _CIFSFS_H */ 118#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 5d0fde18039c..0c2fd17439c8 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -18,6 +18,7 @@
18 */ 18 */
19#include <linux/in.h> 19#include <linux/in.h>
20#include <linux/in6.h> 20#include <linux/in6.h>
21#include <linux/slab.h>
21#include <linux/slow-work.h> 22#include <linux/slow-work.h>
22#include "cifs_fs_sb.h" 23#include "cifs_fs_sb.h"
23#include "cifsacl.h" 24#include "cifsacl.h"
@@ -39,7 +40,7 @@
39 40
40/* 41/*
41 * MAX_REQ is the maximum number of requests that WE will send 42 * MAX_REQ is the maximum number of requests that WE will send
42 * on one socket concurently. It also matches the most common 43 * on one socket concurrently. It also matches the most common
43 * value of max multiplex returned by servers. We may 44 * value of max multiplex returned by servers. We may
44 * eventually want to use the negotiated value (in case 45 * eventually want to use the negotiated value (in case
45 * future servers can handle more) when we are more confident that 46 * future servers can handle more) when we are more confident that
@@ -149,6 +150,7 @@ struct TCP_Server_Info {
149 bool svlocal:1; /* local server or remote */ 150 bool svlocal:1; /* local server or remote */
150 bool noblocksnd; /* use blocking sendmsg */ 151 bool noblocksnd; /* use blocking sendmsg */
151 bool noautotune; /* do not autotune send buf sizes */ 152 bool noautotune; /* do not autotune send buf sizes */
153 bool tcp_nodelay;
152 atomic_t inFlight; /* number of requests on the wire to server */ 154 atomic_t inFlight; /* number of requests on the wire to server */
153#ifdef CONFIG_CIFS_STATS2 155#ifdef CONFIG_CIFS_STATS2
154 atomic_t inSend; /* requests trying to send */ 156 atomic_t inSend; /* requests trying to send */
@@ -204,7 +206,7 @@ struct cifsUidInfo {
204struct cifsSesInfo { 206struct cifsSesInfo {
205 struct list_head smb_ses_list; 207 struct list_head smb_ses_list;
206 struct list_head tcon_list; 208 struct list_head tcon_list;
207 struct semaphore sesSem; 209 struct mutex session_mutex;
208#if 0 210#if 0
209 struct cifsUidInfo *uidInfo; /* pointer to user info */ 211 struct cifsUidInfo *uidInfo; /* pointer to user info */
210#endif 212#endif
@@ -388,6 +390,7 @@ struct cifsInodeInfo {
388 bool clientCanCacheRead:1; /* read oplock */ 390 bool clientCanCacheRead:1; /* read oplock */
389 bool clientCanCacheAll:1; /* read and writebehind oplock */ 391 bool clientCanCacheAll:1; /* read and writebehind oplock */
390 bool delete_pending:1; /* DELETE_ON_CLOSE is set */ 392 bool delete_pending:1; /* DELETE_ON_CLOSE is set */
393 bool invalid_mapping:1; /* pagecache is invalid */
391 u64 server_eof; /* current file size on server */ 394 u64 server_eof; /* current file size on server */
392 u64 uniqueid; /* server inode number */ 395 u64 uniqueid; /* server inode number */
393 struct inode vfs_inode; 396 struct inode vfs_inode;
@@ -499,6 +502,7 @@ struct dfs_info3_param {
499#define CIFS_FATTR_DFS_REFERRAL 0x1 502#define CIFS_FATTR_DFS_REFERRAL 0x1
500#define CIFS_FATTR_DELETE_PENDING 0x2 503#define CIFS_FATTR_DELETE_PENDING 0x2
501#define CIFS_FATTR_NEED_REVAL 0x4 504#define CIFS_FATTR_NEED_REVAL 0x4
505#define CIFS_FATTR_INO_COLLISION 0x8
502 506
503struct cifs_fattr { 507struct cifs_fattr {
504 u32 cf_flags; 508 u32 cf_flags;
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 2d07f890a842..14d036d8db11 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -415,10 +415,10 @@ struct smb_hdr {
415 __u8 WordCount; 415 __u8 WordCount;
416} __attribute__((packed)); 416} __attribute__((packed));
417/* given a pointer to an smb_hdr retrieve the value of byte count */ 417/* given a pointer to an smb_hdr retrieve the value of byte count */
418#define BCC(smb_var) (*(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount))) 418#define BCC(smb_var) (*(__u16 *)((char *)(smb_var) + sizeof(struct smb_hdr) + (2 * (smb_var)->WordCount)))
419#define BCC_LE(smb_var) (*(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount))) 419#define BCC_LE(smb_var) (*(__le16 *)((char *)(smb_var) + sizeof(struct smb_hdr) + (2 * (smb_var)->WordCount)))
420/* given a pointer to an smb_hdr retrieve the pointer to the byte area */ 420/* given a pointer to an smb_hdr retrieve the pointer to the byte area */
421#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount) + 2) 421#define pByteArea(smb_var) ((unsigned char *)(smb_var) + sizeof(struct smb_hdr) + (2 * (smb_var)->WordCount) + 2)
422 422
423/* 423/*
424 * Computer Name Length (since Netbios name was length 16 with last byte 0x20) 424 * Computer Name Length (since Netbios name was length 16 with last byte 0x20)
@@ -1227,7 +1227,7 @@ typedef struct smb_com_setattr_rsp {
1227/* empty wct response to setattr */ 1227/* empty wct response to setattr */
1228 1228
1229/*******************************************************/ 1229/*******************************************************/
1230/* NT Transact structure defintions follow */ 1230/* NT Transact structure definitions follow */
1231/* Currently only ioctl, acl (get security descriptor) */ 1231/* Currently only ioctl, acl (get security descriptor) */
1232/* and notify are implemented */ 1232/* and notify are implemented */
1233/*******************************************************/ 1233/*******************************************************/
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 5646727e33f5..39e47f46dea5 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -104,10 +104,12 @@ extern void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr);
104extern struct inode *cifs_iget(struct super_block *sb, 104extern struct inode *cifs_iget(struct super_block *sb,
105 struct cifs_fattr *fattr); 105 struct cifs_fattr *fattr);
106 106
107extern int cifs_get_file_info(struct file *filp);
107extern int cifs_get_inode_info(struct inode **pinode, 108extern int cifs_get_inode_info(struct inode **pinode,
108 const unsigned char *search_path, 109 const unsigned char *search_path,
109 FILE_ALL_INFO *pfile_info, 110 FILE_ALL_INFO *pfile_info,
110 struct super_block *sb, int xid, const __u16 *pfid); 111 struct super_block *sb, int xid, const __u16 *pfid);
112extern int cifs_get_file_info_unix(struct file *filp);
111extern int cifs_get_inode_info_unix(struct inode **pinode, 113extern int cifs_get_inode_info_unix(struct inode **pinode,
112 const unsigned char *search_path, 114 const unsigned char *search_path,
113 struct super_block *sb, int xid); 115 struct super_block *sb, int xid);
@@ -142,6 +144,8 @@ extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
142extern int CIFSFindClose(const int, struct cifsTconInfo *tcon, 144extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
143 const __u16 search_handle); 145 const __u16 search_handle);
144 146
147extern int CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon,
148 u16 netfid, FILE_ALL_INFO *pFindData);
145extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, 149extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
146 const unsigned char *searchName, 150 const unsigned char *searchName,
147 FILE_ALL_INFO *findData, 151 FILE_ALL_INFO *findData,
@@ -152,6 +156,8 @@ extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
152 FILE_ALL_INFO *findData, 156 FILE_ALL_INFO *findData,
153 const struct nls_table *nls_codepage, int remap); 157 const struct nls_table *nls_codepage, int remap);
154 158
159extern int CIFSSMBUnixQFileInfo(const int xid, struct cifsTconInfo *tcon,
160 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData);
155extern int CIFSSMBUnixQPathInfo(const int xid, 161extern int CIFSSMBUnixQPathInfo(const int xid,
156 struct cifsTconInfo *tcon, 162 struct cifsTconInfo *tcon,
157 const unsigned char *searchName, 163 const unsigned char *searchName,
@@ -363,13 +369,10 @@ extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
363 __u32 filter, struct file *file, int multishot, 369 __u32 filter, struct file *file, int multishot,
364 const struct nls_table *nls_codepage); 370 const struct nls_table *nls_codepage);
365extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, 371extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
366 const unsigned char *searchName, char *EAData, 372 const unsigned char *searchName,
373 const unsigned char *ea_name, char *EAData,
367 size_t bufsize, const struct nls_table *nls_codepage, 374 size_t bufsize, const struct nls_table *nls_codepage,
368 int remap_special_chars); 375 int remap_special_chars);
369extern ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
370 const unsigned char *searchName, const unsigned char *ea_name,
371 unsigned char *ea_value, size_t buf_size,
372 const struct nls_table *nls_codepage, int remap_special_chars);
373extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, 376extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
374 const char *fileName, const char *ea_name, 377 const char *fileName, const char *ea_name,
375 const void *ea_value, const __u16 ea_value_len, 378 const void *ea_value, const __u16 ea_value_len,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 941441d3e386..5d3f29fef532 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -30,6 +30,7 @@
30#include <linux/fs.h> 30#include <linux/fs.h>
31#include <linux/kernel.h> 31#include <linux/kernel.h>
32#include <linux/vfs.h> 32#include <linux/vfs.h>
33#include <linux/slab.h>
33#include <linux/posix_acl_xattr.h> 34#include <linux/posix_acl_xattr.h>
34#include <asm/uaccess.h> 35#include <asm/uaccess.h>
35#include "cifspdu.h" 36#include "cifspdu.h"
@@ -170,19 +171,19 @@ cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command)
170 * need to prevent multiple threads trying to simultaneously 171 * need to prevent multiple threads trying to simultaneously
171 * reconnect the same SMB session 172 * reconnect the same SMB session
172 */ 173 */
173 down(&ses->sesSem); 174 mutex_lock(&ses->session_mutex);
174 if (ses->need_reconnect) 175 if (ses->need_reconnect)
175 rc = cifs_setup_session(0, ses, nls_codepage); 176 rc = cifs_setup_session(0, ses, nls_codepage);
176 177
177 /* do we need to reconnect tcon? */ 178 /* do we need to reconnect tcon? */
178 if (rc || !tcon->need_reconnect) { 179 if (rc || !tcon->need_reconnect) {
179 up(&ses->sesSem); 180 mutex_unlock(&ses->session_mutex);
180 goto out; 181 goto out;
181 } 182 }
182 183
183 mark_open_files_invalid(tcon); 184 mark_open_files_invalid(tcon);
184 rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage); 185 rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
185 up(&ses->sesSem); 186 mutex_unlock(&ses->session_mutex);
186 cFYI(1, ("reconnect tcon rc = %d", rc)); 187 cFYI(1, ("reconnect tcon rc = %d", rc));
187 188
188 if (rc) 189 if (rc)
@@ -500,7 +501,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
500 } else if (pSMBr->hdr.WordCount == 13) { 501 } else if (pSMBr->hdr.WordCount == 13) {
501 cERROR(1, ("mount failed, cifs module not built " 502 cERROR(1, ("mount failed, cifs module not built "
502 "with CIFS_WEAK_PW_HASH support")); 503 "with CIFS_WEAK_PW_HASH support"));
503 rc = -EOPNOTSUPP; 504 rc = -EOPNOTSUPP;
504#endif /* WEAK_PW_HASH */ 505#endif /* WEAK_PW_HASH */
505 goto neg_err_exit; 506 goto neg_err_exit;
506 } else if (pSMBr->hdr.WordCount != 17) { 507 } else if (pSMBr->hdr.WordCount != 17) {
@@ -700,13 +701,13 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
700 if (!ses || !ses->server) 701 if (!ses || !ses->server)
701 return -EIO; 702 return -EIO;
702 703
703 down(&ses->sesSem); 704 mutex_lock(&ses->session_mutex);
704 if (ses->need_reconnect) 705 if (ses->need_reconnect)
705 goto session_already_dead; /* no need to send SMBlogoff if uid 706 goto session_already_dead; /* no need to send SMBlogoff if uid
706 already closed due to reconnect */ 707 already closed due to reconnect */
707 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB); 708 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
708 if (rc) { 709 if (rc) {
709 up(&ses->sesSem); 710 mutex_unlock(&ses->session_mutex);
710 return rc; 711 return rc;
711 } 712 }
712 713
@@ -721,7 +722,7 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
721 pSMB->AndXCommand = 0xFF; 722 pSMB->AndXCommand = 0xFF;
722 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0); 723 rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
723session_already_dead: 724session_already_dead:
724 up(&ses->sesSem); 725 mutex_unlock(&ses->session_mutex);
725 726
726 /* if session dead then we do not need to do ulogoff, 727 /* if session dead then we do not need to do ulogoff,
727 since server closed smb session, no sense reporting 728 since server closed smb session, no sense reporting
@@ -1430,6 +1431,8 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1430 __u32 bytes_sent; 1431 __u32 bytes_sent;
1431 __u16 byte_count; 1432 __u16 byte_count;
1432 1433
1434 *nbytes = 0;
1435
1433 /* cFYI(1, ("write at %lld %d bytes", offset, count));*/ 1436 /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
1434 if (tcon->ses == NULL) 1437 if (tcon->ses == NULL)
1435 return -ECONNABORTED; 1438 return -ECONNABORTED;
@@ -1512,11 +1515,18 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1512 cifs_stats_inc(&tcon->num_writes); 1515 cifs_stats_inc(&tcon->num_writes);
1513 if (rc) { 1516 if (rc) {
1514 cFYI(1, ("Send error in write = %d", rc)); 1517 cFYI(1, ("Send error in write = %d", rc));
1515 *nbytes = 0;
1516 } else { 1518 } else {
1517 *nbytes = le16_to_cpu(pSMBr->CountHigh); 1519 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1518 *nbytes = (*nbytes) << 16; 1520 *nbytes = (*nbytes) << 16;
1519 *nbytes += le16_to_cpu(pSMBr->Count); 1521 *nbytes += le16_to_cpu(pSMBr->Count);
1522
1523 /*
1524 * Mask off high 16 bits when bytes written as returned by the
1525 * server is greater than bytes requested by the client. Some
1526 * OS/2 servers are known to set incorrect CountHigh values.
1527 */
1528 if (*nbytes > count)
1529 *nbytes &= 0xFFFF;
1520 } 1530 }
1521 1531
1522 cifs_buf_release(pSMB); 1532 cifs_buf_release(pSMB);
@@ -1605,6 +1615,14 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1605 *nbytes = le16_to_cpu(pSMBr->CountHigh); 1615 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1606 *nbytes = (*nbytes) << 16; 1616 *nbytes = (*nbytes) << 16;
1607 *nbytes += le16_to_cpu(pSMBr->Count); 1617 *nbytes += le16_to_cpu(pSMBr->Count);
1618
1619 /*
1620 * Mask off high 16 bits when bytes written as returned by the
1621 * server is greater than bytes requested by the client. OS/2
1622 * servers are known to set incorrect CountHigh values.
1623 */
1624 if (*nbytes > count)
1625 *nbytes &= 0xFFFF;
1608 } 1626 }
1609 1627
1610/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ 1628/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
@@ -1793,8 +1811,21 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1793 } 1811 }
1794 parm_data = (struct cifs_posix_lock *) 1812 parm_data = (struct cifs_posix_lock *)
1795 ((char *)&pSMBr->hdr.Protocol + data_offset); 1813 ((char *)&pSMBr->hdr.Protocol + data_offset);
1796 if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK)) 1814 if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
1797 pLockData->fl_type = F_UNLCK; 1815 pLockData->fl_type = F_UNLCK;
1816 else {
1817 if (parm_data->lock_type ==
1818 __constant_cpu_to_le16(CIFS_RDLCK))
1819 pLockData->fl_type = F_RDLCK;
1820 else if (parm_data->lock_type ==
1821 __constant_cpu_to_le16(CIFS_WRLCK))
1822 pLockData->fl_type = F_WRLCK;
1823
1824 pLockData->fl_start = parm_data->start;
1825 pLockData->fl_end = parm_data->start +
1826 parm_data->length - 1;
1827 pLockData->fl_pid = parm_data->pid;
1828 }
1798 } 1829 }
1799 1830
1800plk_err_exit: 1831plk_err_exit:
@@ -3230,8 +3261,72 @@ QInfRetry:
3230 return rc; 3261 return rc;
3231} 3262}
3232 3263
3264int
3265CIFSSMBQFileInfo(const int xid, struct cifsTconInfo *tcon,
3266 u16 netfid, FILE_ALL_INFO *pFindData)
3267{
3268 struct smb_t2_qfi_req *pSMB = NULL;
3269 struct smb_t2_qfi_rsp *pSMBr = NULL;
3270 int rc = 0;
3271 int bytes_returned;
3272 __u16 params, byte_count;
3273
3274QFileInfoRetry:
3275 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3276 (void **) &pSMBr);
3277 if (rc)
3278 return rc;
3279
3280 params = 2 /* level */ + 2 /* fid */;
3281 pSMB->t2.TotalDataCount = 0;
3282 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3283 /* BB find exact max data count below from sess structure BB */
3284 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3285 pSMB->t2.MaxSetupCount = 0;
3286 pSMB->t2.Reserved = 0;
3287 pSMB->t2.Flags = 0;
3288 pSMB->t2.Timeout = 0;
3289 pSMB->t2.Reserved2 = 0;
3290 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3291 Fid) - 4);
3292 pSMB->t2.DataCount = 0;
3293 pSMB->t2.DataOffset = 0;
3294 pSMB->t2.SetupCount = 1;
3295 pSMB->t2.Reserved3 = 0;
3296 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3297 byte_count = params + 1 /* pad */ ;
3298 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3299 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3300 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
3301 pSMB->Pad = 0;
3302 pSMB->Fid = netfid;
3303 pSMB->hdr.smb_buf_length += byte_count;
3304
3305 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3306 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3307 if (rc) {
3308 cFYI(1, ("Send error in QPathInfo = %d", rc));
3309 } else { /* decode response */
3310 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3233 3311
3312 if (rc) /* BB add auto retry on EOPNOTSUPP? */
3313 rc = -EIO;
3314 else if (pSMBr->ByteCount < 40)
3315 rc = -EIO; /* bad smb */
3316 else if (pFindData) {
3317 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3318 memcpy((char *) pFindData,
3319 (char *) &pSMBr->hdr.Protocol +
3320 data_offset, sizeof(FILE_ALL_INFO));
3321 } else
3322 rc = -ENOMEM;
3323 }
3324 cifs_buf_release(pSMB);
3325 if (rc == -EAGAIN)
3326 goto QFileInfoRetry;
3234 3327
3328 return rc;
3329}
3235 3330
3236int 3331int
3237CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, 3332CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
@@ -3335,6 +3430,75 @@ QPathInfoRetry:
3335} 3430}
3336 3431
3337int 3432int
3433CIFSSMBUnixQFileInfo(const int xid, struct cifsTconInfo *tcon,
3434 u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
3435{
3436 struct smb_t2_qfi_req *pSMB = NULL;
3437 struct smb_t2_qfi_rsp *pSMBr = NULL;
3438 int rc = 0;
3439 int bytes_returned;
3440 __u16 params, byte_count;
3441
3442UnixQFileInfoRetry:
3443 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3444 (void **) &pSMBr);
3445 if (rc)
3446 return rc;
3447
3448 params = 2 /* level */ + 2 /* fid */;
3449 pSMB->t2.TotalDataCount = 0;
3450 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
3451 /* BB find exact max data count below from sess structure BB */
3452 pSMB->t2.MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
3453 pSMB->t2.MaxSetupCount = 0;
3454 pSMB->t2.Reserved = 0;
3455 pSMB->t2.Flags = 0;
3456 pSMB->t2.Timeout = 0;
3457 pSMB->t2.Reserved2 = 0;
3458 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
3459 Fid) - 4);
3460 pSMB->t2.DataCount = 0;
3461 pSMB->t2.DataOffset = 0;
3462 pSMB->t2.SetupCount = 1;
3463 pSMB->t2.Reserved3 = 0;
3464 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
3465 byte_count = params + 1 /* pad */ ;
3466 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
3467 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
3468 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
3469 pSMB->Pad = 0;
3470 pSMB->Fid = netfid;
3471 pSMB->hdr.smb_buf_length += byte_count;
3472
3473 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3474 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3475 if (rc) {
3476 cFYI(1, ("Send error in QPathInfo = %d", rc));
3477 } else { /* decode response */
3478 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3479
3480 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3481 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3482 "Unix Extensions can be disabled on mount "
3483 "by specifying the nosfu mount option."));
3484 rc = -EIO; /* bad smb */
3485 } else {
3486 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3487 memcpy((char *) pFindData,
3488 (char *) &pSMBr->hdr.Protocol +
3489 data_offset,
3490 sizeof(FILE_UNIX_BASIC_INFO));
3491 }
3492 }
3493
3494 cifs_buf_release(pSMB);
3495 if (rc == -EAGAIN)
3496 goto UnixQFileInfoRetry;
3497
3498 return rc;
3499}
3500
3501int
3338CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, 3502CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
3339 const unsigned char *searchName, 3503 const unsigned char *searchName,
3340 FILE_UNIX_BASIC_INFO *pFindData, 3504 FILE_UNIX_BASIC_INFO *pFindData,
@@ -3886,7 +4050,7 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3886 goto parse_DFS_referrals_exit; 4050 goto parse_DFS_referrals_exit;
3887 } 4051 }
3888 4052
3889 /* collect neccessary data from referrals */ 4053 /* collect necessary data from referrals */
3890 for (i = 0; i < *num_of_nodes; i++) { 4054 for (i = 0; i < *num_of_nodes; i++) {
3891 char *temp; 4055 char *temp;
3892 int max_len; 4056 int max_len;
@@ -5269,22 +5433,34 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
5269 cifs_buf_release(pSMB); 5433 cifs_buf_release(pSMB);
5270 return rc; 5434 return rc;
5271} 5435}
5436
5272#ifdef CONFIG_CIFS_XATTR 5437#ifdef CONFIG_CIFS_XATTR
5438/*
5439 * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
5440 * function used by listxattr and getxattr type calls. When ea_name is set,
5441 * it looks for that attribute name and stuffs that value into the EAData
5442 * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
5443 * buffer. In both cases, the return value is either the length of the
5444 * resulting data or a negative error code. If EAData is a NULL pointer then
5445 * the data isn't copied to it, but the length is returned.
5446 */
5273ssize_t 5447ssize_t
5274CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, 5448CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
5275 const unsigned char *searchName, 5449 const unsigned char *searchName, const unsigned char *ea_name,
5276 char *EAData, size_t buf_size, 5450 char *EAData, size_t buf_size,
5277 const struct nls_table *nls_codepage, int remap) 5451 const struct nls_table *nls_codepage, int remap)
5278{ 5452{
5279 /* BB assumes one setup word */ 5453 /* BB assumes one setup word */
5280 TRANSACTION2_QPI_REQ *pSMB = NULL; 5454 TRANSACTION2_QPI_REQ *pSMB = NULL;
5281 TRANSACTION2_QPI_RSP *pSMBr = NULL; 5455 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5282 int rc = 0; 5456 int rc = 0;
5283 int bytes_returned; 5457 int bytes_returned;
5284 int name_len; 5458 int list_len;
5459 struct fealist *ea_response_data;
5285 struct fea *temp_fea; 5460 struct fea *temp_fea;
5286 char *temp_ptr; 5461 char *temp_ptr;
5287 __u16 params, byte_count; 5462 char *end_of_smb;
5463 __u16 params, byte_count, data_offset;
5288 5464
5289 cFYI(1, ("In Query All EAs path %s", searchName)); 5465 cFYI(1, ("In Query All EAs path %s", searchName));
5290QAllEAsRetry: 5466QAllEAsRetry:
@@ -5294,22 +5470,22 @@ QAllEAsRetry:
5294 return rc; 5470 return rc;
5295 5471
5296 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 5472 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
5297 name_len = 5473 list_len =
5298 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, 5474 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
5299 PATH_MAX, nls_codepage, remap); 5475 PATH_MAX, nls_codepage, remap);
5300 name_len++; /* trailing null */ 5476 list_len++; /* trailing null */
5301 name_len *= 2; 5477 list_len *= 2;
5302 } else { /* BB improve the check for buffer overruns BB */ 5478 } else { /* BB improve the check for buffer overruns BB */
5303 name_len = strnlen(searchName, PATH_MAX); 5479 list_len = strnlen(searchName, PATH_MAX);
5304 name_len++; /* trailing null */ 5480 list_len++; /* trailing null */
5305 strncpy(pSMB->FileName, searchName, name_len); 5481 strncpy(pSMB->FileName, searchName, list_len);
5306 } 5482 }
5307 5483
5308 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; 5484 params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
5309 pSMB->TotalDataCount = 0; 5485 pSMB->TotalDataCount = 0;
5310 pSMB->MaxParameterCount = cpu_to_le16(2); 5486 pSMB->MaxParameterCount = cpu_to_le16(2);
5311 /* BB find exact max SMB PDU from sess structure BB */ 5487 /* BB find exact max SMB PDU from sess structure BB */
5312 pSMB->MaxDataCount = cpu_to_le16(4000); 5488 pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
5313 pSMB->MaxSetupCount = 0; 5489 pSMB->MaxSetupCount = 0;
5314 pSMB->Reserved = 0; 5490 pSMB->Reserved = 0;
5315 pSMB->Flags = 0; 5491 pSMB->Flags = 0;
@@ -5334,237 +5510,117 @@ QAllEAsRetry:
5334 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 5510 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
5335 if (rc) { 5511 if (rc) {
5336 cFYI(1, ("Send error in QueryAllEAs = %d", rc)); 5512 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
5337 } else { /* decode response */ 5513 goto QAllEAsOut;
5338 rc = validate_t2((struct smb_t2_rsp *)pSMBr); 5514 }
5339 5515
5340 /* BB also check enough total bytes returned */ 5516
5341 /* BB we need to improve the validity checking 5517 /* BB also check enough total bytes returned */
5342 of these trans2 responses */ 5518 /* BB we need to improve the validity checking
5343 if (rc || (pSMBr->ByteCount < 4)) 5519 of these trans2 responses */
5344 rc = -EIO; /* bad smb */ 5520
5345 /* else if (pFindData){ 5521 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
5346 memcpy((char *) pFindData, 5522 if (rc || (pSMBr->ByteCount < 4)) {
5347 (char *) &pSMBr->hdr.Protocol + 5523 rc = -EIO; /* bad smb */
5348 data_offset, kl); 5524 goto QAllEAsOut;
5349 }*/ else {
5350 /* check that length of list is not more than bcc */
5351 /* check that each entry does not go beyond length
5352 of list */
5353 /* check that each element of each entry does not
5354 go beyond end of list */
5355 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5356 struct fealist *ea_response_data;
5357 rc = 0;
5358 /* validate_trans2_offsets() */
5359 /* BB check if start of smb + data_offset > &bcc+ bcc */
5360 ea_response_data = (struct fealist *)
5361 (((char *) &pSMBr->hdr.Protocol) +
5362 data_offset);
5363 name_len = le32_to_cpu(ea_response_data->list_len);
5364 cFYI(1, ("ea length %d", name_len));
5365 if (name_len <= 8) {
5366 /* returned EA size zeroed at top of function */
5367 cFYI(1, ("empty EA list returned from server"));
5368 } else {
5369 /* account for ea list len */
5370 name_len -= 4;
5371 temp_fea = ea_response_data->list;
5372 temp_ptr = (char *)temp_fea;
5373 while (name_len > 0) {
5374 __u16 value_len;
5375 name_len -= 4;
5376 temp_ptr += 4;
5377 rc += temp_fea->name_len;
5378 /* account for prefix user. and trailing null */
5379 rc = rc + 5 + 1;
5380 if (rc < (int)buf_size) {
5381 memcpy(EAData, "user.", 5);
5382 EAData += 5;
5383 memcpy(EAData, temp_ptr,
5384 temp_fea->name_len);
5385 EAData += temp_fea->name_len;
5386 /* null terminate name */
5387 *EAData = 0;
5388 EAData = EAData + 1;
5389 } else if (buf_size == 0) {
5390 /* skip copy - calc size only */
5391 } else {
5392 /* stop before overrun buffer */
5393 rc = -ERANGE;
5394 break;
5395 }
5396 name_len -= temp_fea->name_len;
5397 temp_ptr += temp_fea->name_len;
5398 /* account for trailing null */
5399 name_len--;
5400 temp_ptr++;
5401 value_len =
5402 le16_to_cpu(temp_fea->value_len);
5403 name_len -= value_len;
5404 temp_ptr += value_len;
5405 /* BB check that temp_ptr is still
5406 within the SMB BB*/
5407
5408 /* no trailing null to account for
5409 in value len */
5410 /* go on to next EA */
5411 temp_fea = (struct fea *)temp_ptr;
5412 }
5413 }
5414 }
5415 } 5525 }
5416 cifs_buf_release(pSMB);
5417 if (rc == -EAGAIN)
5418 goto QAllEAsRetry;
5419 5526
5420 return (ssize_t)rc; 5527 /* check that length of list is not more than bcc */
5421} 5528 /* check that each entry does not go beyond length
5529 of list */
5530 /* check that each element of each entry does not
5531 go beyond end of list */
5532 /* validate_trans2_offsets() */
5533 /* BB check if start of smb + data_offset > &bcc+ bcc */
5422 5534
5423ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon, 5535 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5424 const unsigned char *searchName, const unsigned char *ea_name, 5536 ea_response_data = (struct fealist *)
5425 unsigned char *ea_value, size_t buf_size, 5537 (((char *) &pSMBr->hdr.Protocol) + data_offset);
5426 const struct nls_table *nls_codepage, int remap)
5427{
5428 TRANSACTION2_QPI_REQ *pSMB = NULL;
5429 TRANSACTION2_QPI_RSP *pSMBr = NULL;
5430 int rc = 0;
5431 int bytes_returned;
5432 int name_len;
5433 struct fea *temp_fea;
5434 char *temp_ptr;
5435 __u16 params, byte_count;
5436 5538
5437 cFYI(1, ("In Query EA path %s", searchName)); 5539 list_len = le32_to_cpu(ea_response_data->list_len);
5438QEARetry: 5540 cFYI(1, ("ea length %d", list_len));
5439 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, 5541 if (list_len <= 8) {
5440 (void **) &pSMBr); 5542 cFYI(1, ("empty EA list returned from server"));
5441 if (rc) 5543 goto QAllEAsOut;
5442 return rc; 5544 }
5443 5545
5444 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 5546 /* make sure list_len doesn't go past end of SMB */
5445 name_len = 5547 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr);
5446 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, 5548 if ((char *)ea_response_data + list_len > end_of_smb) {
5447 PATH_MAX, nls_codepage, remap); 5549 cFYI(1, ("EA list appears to go beyond SMB"));
5448 name_len++; /* trailing null */ 5550 rc = -EIO;
5449 name_len *= 2; 5551 goto QAllEAsOut;
5450 } else { /* BB improve the check for buffer overruns BB */
5451 name_len = strnlen(searchName, PATH_MAX);
5452 name_len++; /* trailing null */
5453 strncpy(pSMB->FileName, searchName, name_len);
5454 } 5552 }
5455 5553
5456 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; 5554 /* account for ea list len */
5457 pSMB->TotalDataCount = 0; 5555 list_len -= 4;
5458 pSMB->MaxParameterCount = cpu_to_le16(2); 5556 temp_fea = ea_response_data->list;
5459 /* BB find exact max SMB PDU from sess structure BB */ 5557 temp_ptr = (char *)temp_fea;
5460 pSMB->MaxDataCount = cpu_to_le16(4000); 5558 while (list_len > 0) {
5461 pSMB->MaxSetupCount = 0; 5559 unsigned int name_len;
5462 pSMB->Reserved = 0; 5560 __u16 value_len;
5463 pSMB->Flags = 0; 5561
5464 pSMB->Timeout = 0; 5562 list_len -= 4;
5465 pSMB->Reserved2 = 0; 5563 temp_ptr += 4;
5466 pSMB->ParameterOffset = cpu_to_le16(offsetof( 5564 /* make sure we can read name_len and value_len */
5467 struct smb_com_transaction2_qpi_req, InformationLevel) - 4); 5565 if (list_len < 0) {
5468 pSMB->DataCount = 0; 5566 cFYI(1, ("EA entry goes beyond length of list"));
5469 pSMB->DataOffset = 0; 5567 rc = -EIO;
5470 pSMB->SetupCount = 1; 5568 goto QAllEAsOut;
5471 pSMB->Reserved3 = 0; 5569 }
5472 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
5473 byte_count = params + 1 /* pad */ ;
5474 pSMB->TotalParameterCount = cpu_to_le16(params);
5475 pSMB->ParameterCount = pSMB->TotalParameterCount;
5476 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
5477 pSMB->Reserved4 = 0;
5478 pSMB->hdr.smb_buf_length += byte_count;
5479 pSMB->ByteCount = cpu_to_le16(byte_count);
5480 5570
5481 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 5571 name_len = temp_fea->name_len;
5482 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 5572 value_len = le16_to_cpu(temp_fea->value_len);
5483 if (rc) { 5573 list_len -= name_len + 1 + value_len;
5484 cFYI(1, ("Send error in Query EA = %d", rc)); 5574 if (list_len < 0) {
5485 } else { /* decode response */ 5575 cFYI(1, ("EA entry goes beyond length of list"));
5486 rc = validate_t2((struct smb_t2_rsp *)pSMBr); 5576 rc = -EIO;
5577 goto QAllEAsOut;
5578 }
5487 5579
5488 /* BB also check enough total bytes returned */ 5580 if (ea_name) {
5489 /* BB we need to improve the validity checking 5581 if (strncmp(ea_name, temp_ptr, name_len) == 0) {
5490 of these trans2 responses */ 5582 temp_ptr += name_len + 1;
5491 if (rc || (pSMBr->ByteCount < 4)) 5583 rc = value_len;
5492 rc = -EIO; /* bad smb */ 5584 if (buf_size == 0)
5493 /* else if (pFindData){ 5585 goto QAllEAsOut;
5494 memcpy((char *) pFindData, 5586 if ((size_t)value_len > buf_size) {
5495 (char *) &pSMBr->hdr.Protocol + 5587 rc = -ERANGE;
5496 data_offset, kl); 5588 goto QAllEAsOut;
5497 }*/ else {
5498 /* check that length of list is not more than bcc */
5499 /* check that each entry does not go beyond length
5500 of list */
5501 /* check that each element of each entry does not
5502 go beyond end of list */
5503 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
5504 struct fealist *ea_response_data;
5505 rc = -ENODATA;
5506 /* validate_trans2_offsets() */
5507 /* BB check if start of smb + data_offset > &bcc+ bcc*/
5508 ea_response_data = (struct fealist *)
5509 (((char *) &pSMBr->hdr.Protocol) +
5510 data_offset);
5511 name_len = le32_to_cpu(ea_response_data->list_len);
5512 cFYI(1, ("ea length %d", name_len));
5513 if (name_len <= 8) {
5514 /* returned EA size zeroed at top of function */
5515 cFYI(1, ("empty EA list returned from server"));
5516 } else {
5517 /* account for ea list len */
5518 name_len -= 4;
5519 temp_fea = ea_response_data->list;
5520 temp_ptr = (char *)temp_fea;
5521 /* loop through checking if we have a matching
5522 name and then return the associated value */
5523 while (name_len > 0) {
5524 __u16 value_len;
5525 name_len -= 4;
5526 temp_ptr += 4;
5527 value_len =
5528 le16_to_cpu(temp_fea->value_len);
5529 /* BB validate that value_len falls within SMB,
5530 even though maximum for name_len is 255 */
5531 if (memcmp(temp_fea->name, ea_name,
5532 temp_fea->name_len) == 0) {
5533 /* found a match */
5534 rc = value_len;
5535 /* account for prefix user. and trailing null */
5536 if (rc <= (int)buf_size) {
5537 memcpy(ea_value,
5538 temp_fea->name+temp_fea->name_len+1,
5539 rc);
5540 /* ea values, unlike ea
5541 names, are not null
5542 terminated */
5543 } else if (buf_size == 0) {
5544 /* skip copy - calc size only */
5545 } else {
5546 /* stop before overrun buffer */
5547 rc = -ERANGE;
5548 }
5549 break;
5550 }
5551 name_len -= temp_fea->name_len;
5552 temp_ptr += temp_fea->name_len;
5553 /* account for trailing null */
5554 name_len--;
5555 temp_ptr++;
5556 name_len -= value_len;
5557 temp_ptr += value_len;
5558 /* No trailing null to account for in
5559 value_len. Go on to next EA */
5560 temp_fea = (struct fea *)temp_ptr;
5561 } 5589 }
5590 memcpy(EAData, temp_ptr, value_len);
5591 goto QAllEAsOut;
5592 }
5593 } else {
5594 /* account for prefix user. and trailing null */
5595 rc += (5 + 1 + name_len);
5596 if (rc < (int) buf_size) {
5597 memcpy(EAData, "user.", 5);
5598 EAData += 5;
5599 memcpy(EAData, temp_ptr, name_len);
5600 EAData += name_len;
5601 /* null terminate name */
5602 *EAData = 0;
5603 ++EAData;
5604 } else if (buf_size == 0) {
5605 /* skip copy - calc size only */
5606 } else {
5607 /* stop before overrun buffer */
5608 rc = -ERANGE;
5609 break;
5562 } 5610 }
5563 } 5611 }
5612 temp_ptr += name_len + 1 + value_len;
5613 temp_fea = (struct fea *)temp_ptr;
5564 } 5614 }
5615
5616 /* didn't find the named attribute */
5617 if (ea_name)
5618 rc = -ENODATA;
5619
5620QAllEAsOut:
5565 cifs_buf_release(pSMB); 5621 cifs_buf_release(pSMB);
5566 if (rc == -EAGAIN) 5622 if (rc == -EAGAIN)
5567 goto QEARetry; 5623 goto QAllEAsRetry;
5568 5624
5569 return (ssize_t)rc; 5625 return (ssize_t)rc;
5570} 5626}
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 63ea83ff687f..d9566bf8f917 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -23,6 +23,7 @@
23#include <linux/string.h> 23#include <linux/string.h>
24#include <linux/list.h> 24#include <linux/list.h>
25#include <linux/wait.h> 25#include <linux/wait.h>
26#include <linux/slab.h>
26#include <linux/pagemap.h> 27#include <linux/pagemap.h>
27#include <linux/ctype.h> 28#include <linux/ctype.h>
28#include <linux/utsname.h> 29#include <linux/utsname.h>
@@ -98,7 +99,7 @@ struct smb_vol {
98 bool nostrictsync:1; /* do not force expensive SMBflush on every sync */ 99 bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
99 unsigned int rsize; 100 unsigned int rsize;
100 unsigned int wsize; 101 unsigned int wsize;
101 unsigned int sockopt; 102 bool sockopt_tcp_nodelay:1;
102 unsigned short int port; 103 unsigned short int port;
103 char *prepath; 104 char *prepath;
104}; 105};
@@ -1142,9 +1143,11 @@ cifs_parse_mount_options(char *options, const char *devname,
1142 simple_strtoul(value, &value, 0); 1143 simple_strtoul(value, &value, 0);
1143 } 1144 }
1144 } else if (strnicmp(data, "sockopt", 5) == 0) { 1145 } else if (strnicmp(data, "sockopt", 5) == 0) {
1145 if (value && *value) { 1146 if (!value || !*value) {
1146 vol->sockopt = 1147 cERROR(1, ("no socket option specified"));
1147 simple_strtoul(value, &value, 0); 1148 continue;
1149 } else if (strnicmp(value, "TCP_NODELAY", 11) == 0) {
1150 vol->sockopt_tcp_nodelay = 1;
1148 } 1151 }
1149 } else if (strnicmp(data, "netbiosname", 4) == 0) { 1152 } else if (strnicmp(data, "netbiosname", 4) == 0) {
1150 if (!value || !*value || (*value == ' ')) { 1153 if (!value || !*value || (*value == ' ')) {
@@ -1514,6 +1517,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
1514 1517
1515 tcp_ses->noblocksnd = volume_info->noblocksnd; 1518 tcp_ses->noblocksnd = volume_info->noblocksnd;
1516 tcp_ses->noautotune = volume_info->noautotune; 1519 tcp_ses->noautotune = volume_info->noautotune;
1520 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
1517 atomic_set(&tcp_ses->inFlight, 0); 1521 atomic_set(&tcp_ses->inFlight, 0);
1518 init_waitqueue_head(&tcp_ses->response_q); 1522 init_waitqueue_head(&tcp_ses->response_q);
1519 init_waitqueue_head(&tcp_ses->request_q); 1523 init_waitqueue_head(&tcp_ses->request_q);
@@ -1764,6 +1768,7 @@ static int
1764ipv4_connect(struct TCP_Server_Info *server) 1768ipv4_connect(struct TCP_Server_Info *server)
1765{ 1769{
1766 int rc = 0; 1770 int rc = 0;
1771 int val;
1767 bool connected = false; 1772 bool connected = false;
1768 __be16 orig_port = 0; 1773 __be16 orig_port = 0;
1769 struct socket *socket = server->ssocket; 1774 struct socket *socket = server->ssocket;
@@ -1845,6 +1850,14 @@ ipv4_connect(struct TCP_Server_Info *server)
1845 socket->sk->sk_rcvbuf = 140 * 1024; 1850 socket->sk->sk_rcvbuf = 140 * 1024;
1846 } 1851 }
1847 1852
1853 if (server->tcp_nodelay) {
1854 val = 1;
1855 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
1856 (char *)&val, sizeof(val));
1857 if (rc)
1858 cFYI(1, ("set TCP_NODELAY socket option error %d", rc));
1859 }
1860
1848 cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx", 1861 cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
1849 socket->sk->sk_sndbuf, 1862 socket->sk->sk_sndbuf,
1850 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo)); 1863 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo));
@@ -1916,6 +1929,7 @@ static int
1916ipv6_connect(struct TCP_Server_Info *server) 1929ipv6_connect(struct TCP_Server_Info *server)
1917{ 1930{
1918 int rc = 0; 1931 int rc = 0;
1932 int val;
1919 bool connected = false; 1933 bool connected = false;
1920 __be16 orig_port = 0; 1934 __be16 orig_port = 0;
1921 struct socket *socket = server->ssocket; 1935 struct socket *socket = server->ssocket;
@@ -1987,6 +2001,15 @@ ipv6_connect(struct TCP_Server_Info *server)
1987 */ 2001 */
1988 socket->sk->sk_rcvtimeo = 7 * HZ; 2002 socket->sk->sk_rcvtimeo = 7 * HZ;
1989 socket->sk->sk_sndtimeo = 5 * HZ; 2003 socket->sk->sk_sndtimeo = 5 * HZ;
2004
2005 if (server->tcp_nodelay) {
2006 val = 1;
2007 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
2008 (char *)&val, sizeof(val));
2009 if (rc)
2010 cFYI(1, ("set TCP_NODELAY socket option error %d", rc));
2011 }
2012
1990 server->ssocket = socket; 2013 server->ssocket = socket;
1991 2014
1992 return rc; 2015 return rc;
@@ -2287,12 +2310,12 @@ int
2287cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, 2310cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2288 char *mount_data_global, const char *devname) 2311 char *mount_data_global, const char *devname)
2289{ 2312{
2290 int rc = 0; 2313 int rc;
2291 int xid; 2314 int xid;
2292 struct smb_vol *volume_info; 2315 struct smb_vol *volume_info;
2293 struct cifsSesInfo *pSesInfo = NULL; 2316 struct cifsSesInfo *pSesInfo;
2294 struct cifsTconInfo *tcon = NULL; 2317 struct cifsTconInfo *tcon;
2295 struct TCP_Server_Info *srvTcp = NULL; 2318 struct TCP_Server_Info *srvTcp;
2296 char *full_path; 2319 char *full_path;
2297 char *mount_data = mount_data_global; 2320 char *mount_data = mount_data_global;
2298#ifdef CONFIG_CIFS_DFS_UPCALL 2321#ifdef CONFIG_CIFS_DFS_UPCALL
@@ -2301,6 +2324,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2301 int referral_walks_count = 0; 2324 int referral_walks_count = 0;
2302try_mount_again: 2325try_mount_again:
2303#endif 2326#endif
2327 rc = 0;
2328 tcon = NULL;
2329 pSesInfo = NULL;
2330 srvTcp = NULL;
2304 full_path = NULL; 2331 full_path = NULL;
2305 2332
2306 xid = GetXid(); 2333 xid = GetXid();
@@ -2362,13 +2389,13 @@ try_mount_again:
2362 */ 2389 */
2363 cifs_put_tcp_session(srvTcp); 2390 cifs_put_tcp_session(srvTcp);
2364 2391
2365 down(&pSesInfo->sesSem); 2392 mutex_lock(&pSesInfo->session_mutex);
2366 if (pSesInfo->need_reconnect) { 2393 if (pSesInfo->need_reconnect) {
2367 cFYI(1, ("Session needs reconnect")); 2394 cFYI(1, ("Session needs reconnect"));
2368 rc = cifs_setup_session(xid, pSesInfo, 2395 rc = cifs_setup_session(xid, pSesInfo,
2369 cifs_sb->local_nls); 2396 cifs_sb->local_nls);
2370 } 2397 }
2371 up(&pSesInfo->sesSem); 2398 mutex_unlock(&pSesInfo->session_mutex);
2372 } else if (!rc) { 2399 } else if (!rc) {
2373 cFYI(1, ("Existing smb sess not found")); 2400 cFYI(1, ("Existing smb sess not found"));
2374 pSesInfo = sesInfoAlloc(); 2401 pSesInfo = sesInfoAlloc();
@@ -2411,12 +2438,12 @@ try_mount_again:
2411 } 2438 }
2412 pSesInfo->linux_uid = volume_info->linux_uid; 2439 pSesInfo->linux_uid = volume_info->linux_uid;
2413 pSesInfo->overrideSecFlg = volume_info->secFlg; 2440 pSesInfo->overrideSecFlg = volume_info->secFlg;
2414 down(&pSesInfo->sesSem); 2441 mutex_lock(&pSesInfo->session_mutex);
2415 2442
2416 /* BB FIXME need to pass vol->secFlgs BB */ 2443 /* BB FIXME need to pass vol->secFlgs BB */
2417 rc = cifs_setup_session(xid, pSesInfo, 2444 rc = cifs_setup_session(xid, pSesInfo,
2418 cifs_sb->local_nls); 2445 cifs_sb->local_nls);
2419 up(&pSesInfo->sesSem); 2446 mutex_unlock(&pSesInfo->session_mutex);
2420 } 2447 }
2421 2448
2422 /* search for existing tcon to this server share */ 2449 /* search for existing tcon to this server share */
@@ -2597,6 +2624,7 @@ remote_path_check:
2597 2624
2598 cleanup_volume_info(&volume_info); 2625 cleanup_volume_info(&volume_info);
2599 referral_walks_count++; 2626 referral_walks_count++;
2627 FreeXid(xid);
2600 goto try_mount_again; 2628 goto try_mount_again;
2601 } 2629 }
2602#else /* No DFS support, return error on mount */ 2630#else /* No DFS support, return error on mount */
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 1f42f772865a..e9f7ecc2714b 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -214,7 +214,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
214 posix_flags |= SMB_O_EXCL; 214 posix_flags |= SMB_O_EXCL;
215 if (oflags & O_TRUNC) 215 if (oflags & O_TRUNC)
216 posix_flags |= SMB_O_TRUNC; 216 posix_flags |= SMB_O_TRUNC;
217 if (oflags & O_SYNC) 217 /* be safe and imply O_SYNC for O_DSYNC */
218 if (oflags & O_DSYNC)
218 posix_flags |= SMB_O_SYNC; 219 posix_flags |= SMB_O_SYNC;
219 if (oflags & O_DIRECTORY) 220 if (oflags & O_DIRECTORY)
220 posix_flags |= SMB_O_DIRECTORY; 221 posix_flags |= SMB_O_DIRECTORY;
@@ -738,7 +739,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
738 int isValid = 1; 739 int isValid = 1;
739 740
740 if (direntry->d_inode) { 741 if (direntry->d_inode) {
741 if (cifs_revalidate(direntry)) 742 if (cifs_revalidate_dentry(direntry))
742 return 0; 743 return 0;
743 } else { 744 } else {
744 cFYI(1, ("neg dentry 0x%p name = %s", 745 cFYI(1, ("neg dentry 0x%p name = %s",
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c
index 87948147d7ec..6f8a0e3fb25b 100644
--- a/fs/cifs/dns_resolve.c
+++ b/fs/cifs/dns_resolve.c
@@ -23,6 +23,7 @@
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */ 24 */
25 25
26#include <linux/slab.h>
26#include <keys/user-type.h> 27#include <keys/user-type.h>
27#include "dns_resolve.h" 28#include "dns_resolve.h"
28#include "cifsglob.h" 29#include "cifsglob.h"
diff --git a/fs/cifs/export.c b/fs/cifs/export.c
index 75949d6a5f1b..6177f7cca16a 100644
--- a/fs/cifs/export.c
+++ b/fs/cifs/export.c
@@ -24,7 +24,7 @@
24 */ 24 */
25 25
26 /* 26 /*
27 * See Documentation/filesystems/Exporting 27 * See Documentation/filesystems/nfs/Exporting
28 * and examples in fs/exportfs 28 * and examples in fs/exportfs
29 * 29 *
30 * Since cifs is a network file system, an "fsid" must be included for 30 * Since cifs is a network file system, an "fsid" must be included for
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 429337eb7afe..9b11a8f56f3a 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -31,6 +31,7 @@
31#include <linux/task_io_accounting_ops.h> 31#include <linux/task_io_accounting_ops.h>
32#include <linux/delay.h> 32#include <linux/delay.h>
33#include <linux/mount.h> 33#include <linux/mount.h>
34#include <linux/slab.h>
34#include <asm/div64.h> 35#include <asm/div64.h>
35#include "cifsfs.h" 36#include "cifsfs.h"
36#include "cifspdu.h" 37#include "cifspdu.h"
@@ -76,8 +77,10 @@ static inline fmode_t cifs_posix_convert_flags(unsigned int flags)
76 reopening a file. They had their effect on the original open */ 77 reopening a file. They had their effect on the original open */
77 if (flags & O_APPEND) 78 if (flags & O_APPEND)
78 posix_flags |= (fmode_t)O_APPEND; 79 posix_flags |= (fmode_t)O_APPEND;
79 if (flags & O_SYNC) 80 if (flags & O_DSYNC)
80 posix_flags |= (fmode_t)O_SYNC; 81 posix_flags |= (fmode_t)O_DSYNC;
82 if (flags & __O_SYNC)
83 posix_flags |= (fmode_t)__O_SYNC;
81 if (flags & O_DIRECTORY) 84 if (flags & O_DIRECTORY)
82 posix_flags |= (fmode_t)O_DIRECTORY; 85 posix_flags |= (fmode_t)O_DIRECTORY;
83 if (flags & O_NOFOLLOW) 86 if (flags & O_NOFOLLOW)
@@ -217,8 +220,8 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
217 cFYI(1, ("inode unchanged on server")); 220 cFYI(1, ("inode unchanged on server"));
218 } else { 221 } else {
219 if (file->f_path.dentry->d_inode->i_mapping) { 222 if (file->f_path.dentry->d_inode->i_mapping) {
220 /* BB no need to lock inode until after invalidate 223 /* BB no need to lock inode until after invalidate
221 since namei code should already have it locked? */ 224 since namei code should already have it locked? */
222 rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping); 225 rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping);
223 if (rc != 0) 226 if (rc != 0)
224 CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc; 227 CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc;
@@ -836,8 +839,32 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
836 839
837 } else { 840 } else {
838 /* if rc == ERR_SHARING_VIOLATION ? */ 841 /* if rc == ERR_SHARING_VIOLATION ? */
839 rc = 0; /* do not change lock type to unlock 842 rc = 0;
840 since range in use */ 843
844 if (lockType & LOCKING_ANDX_SHARED_LOCK) {
845 pfLock->fl_type = F_WRLCK;
846 } else {
847 rc = CIFSSMBLock(xid, tcon, netfid, length,
848 pfLock->fl_start, 0, 1,
849 lockType | LOCKING_ANDX_SHARED_LOCK,
850 0 /* wait flag */);
851 if (rc == 0) {
852 rc = CIFSSMBLock(xid, tcon, netfid,
853 length, pfLock->fl_start, 1, 0,
854 lockType |
855 LOCKING_ANDX_SHARED_LOCK,
856 0 /* wait flag */);
857 pfLock->fl_type = F_RDLCK;
858 if (rc != 0)
859 cERROR(1, ("Error unlocking "
860 "previously locked range %d "
861 "during test of lock", rc));
862 rc = 0;
863 } else {
864 pfLock->fl_type = F_WRLCK;
865 rc = 0;
866 }
867 }
841 } 868 }
842 869
843 FreeXid(xid); 870 FreeXid(xid);
@@ -1888,11 +1915,10 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1888 1915
1889int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) 1916int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
1890{ 1917{
1891 struct dentry *dentry = file->f_path.dentry;
1892 int rc, xid; 1918 int rc, xid;
1893 1919
1894 xid = GetXid(); 1920 xid = GetXid();
1895 rc = cifs_revalidate(dentry); 1921 rc = cifs_revalidate_file(file);
1896 if (rc) { 1922 if (rc) {
1897 cFYI(1, ("Validation prior to mmap failed, error=%d", rc)); 1923 cFYI(1, ("Validation prior to mmap failed, error=%d", rc));
1898 FreeXid(xid); 1924 FreeXid(xid);
@@ -2287,9 +2313,9 @@ cifs_oplock_break(struct slow_work *work)
2287 if (inode && S_ISREG(inode->i_mode)) { 2313 if (inode && S_ISREG(inode->i_mode)) {
2288#ifdef CONFIG_CIFS_EXPERIMENTAL 2314#ifdef CONFIG_CIFS_EXPERIMENTAL
2289 if (cinode->clientCanCacheAll == 0) 2315 if (cinode->clientCanCacheAll == 0)
2290 break_lease(inode, FMODE_READ); 2316 break_lease(inode, O_RDONLY);
2291 else if (cinode->clientCanCacheRead == 0) 2317 else if (cinode->clientCanCacheRead == 0)
2292 break_lease(inode, FMODE_WRITE); 2318 break_lease(inode, O_WRONLY);
2293#endif 2319#endif
2294 rc = filemap_fdatawrite(inode->i_mapping); 2320 rc = filemap_fdatawrite(inode->i_mapping);
2295 if (cinode->clientCanCacheRead == 0) { 2321 if (cinode->clientCanCacheRead == 0) {
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index cababd8a52df..29b9ea244c81 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -20,6 +20,7 @@
20 */ 20 */
21#include <linux/fs.h> 21#include <linux/fs.h>
22#include <linux/stat.h> 22#include <linux/stat.h>
23#include <linux/slab.h>
23#include <linux/pagemap.h> 24#include <linux/pagemap.h>
24#include <asm/div64.h> 25#include <asm/div64.h>
25#include "cifsfs.h" 26#include "cifsfs.h"
@@ -77,6 +78,41 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
77 } 78 }
78} 79}
79 80
81/* check inode attributes against fattr. If they don't match, tag the
82 * inode for cache invalidation
83 */
84static void
85cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
86{
87 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
88
89 cFYI(1, ("%s: revalidating inode %llu", __func__, cifs_i->uniqueid));
90
91 if (inode->i_state & I_NEW) {
92 cFYI(1, ("%s: inode %llu is new", __func__, cifs_i->uniqueid));
93 return;
94 }
95
96 /* don't bother with revalidation if we have an oplock */
97 if (cifs_i->clientCanCacheRead) {
98 cFYI(1, ("%s: inode %llu is oplocked", __func__,
99 cifs_i->uniqueid));
100 return;
101 }
102
103 /* revalidate if mtime or size have changed */
104 if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) &&
105 cifs_i->server_eof == fattr->cf_eof) {
106 cFYI(1, ("%s: inode %llu is unchanged", __func__,
107 cifs_i->uniqueid));
108 return;
109 }
110
111 cFYI(1, ("%s: invalidating inode %llu mapping", __func__,
112 cifs_i->uniqueid));
113 cifs_i->invalid_mapping = true;
114}
115
80/* populate an inode with info from a cifs_fattr struct */ 116/* populate an inode with info from a cifs_fattr struct */
81void 117void
82cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) 118cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
@@ -85,6 +121,8 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
85 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 121 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
86 unsigned long oldtime = cifs_i->time; 122 unsigned long oldtime = cifs_i->time;
87 123
124 cifs_revalidate_cache(inode, fattr);
125
88 inode->i_atime = fattr->cf_atime; 126 inode->i_atime = fattr->cf_atime;
89 inode->i_mtime = fattr->cf_mtime; 127 inode->i_mtime = fattr->cf_mtime;
90 inode->i_ctime = fattr->cf_ctime; 128 inode->i_ctime = fattr->cf_ctime;
@@ -111,6 +149,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
111 149
112 cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; 150 cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
113 151
152 cifs_i->server_eof = fattr->cf_eof;
114 /* 153 /*
115 * Can't safely change the file size here if the client is writing to 154 * Can't safely change the file size here if the client is writing to
116 * it due to potential races. 155 * it due to potential races.
@@ -230,6 +269,31 @@ cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
230 fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; 269 fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
231} 270}
232 271
272int cifs_get_file_info_unix(struct file *filp)
273{
274 int rc;
275 int xid;
276 FILE_UNIX_BASIC_INFO find_data;
277 struct cifs_fattr fattr;
278 struct inode *inode = filp->f_path.dentry->d_inode;
279 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
280 struct cifsTconInfo *tcon = cifs_sb->tcon;
281 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
282
283 xid = GetXid();
284 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data);
285 if (!rc) {
286 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
287 } else if (rc == -EREMOTE) {
288 cifs_create_dfs_fattr(&fattr, inode->i_sb);
289 rc = 0;
290 }
291
292 cifs_fattr_to_inode(inode, &fattr);
293 FreeXid(xid);
294 return rc;
295}
296
233int cifs_get_inode_info_unix(struct inode **pinode, 297int cifs_get_inode_info_unix(struct inode **pinode,
234 const unsigned char *full_path, 298 const unsigned char *full_path,
235 struct super_block *sb, int xid) 299 struct super_block *sb, int xid)
@@ -366,7 +430,7 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
366 char ea_value[4]; 430 char ea_value[4];
367 __u32 mode; 431 __u32 mode;
368 432
369 rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", 433 rc = CIFSSMBQAllEAs(xid, cifs_sb->tcon, path, "SETFILEBITS",
370 ea_value, 4 /* size of buf */, cifs_sb->local_nls, 434 ea_value, 4 /* size of buf */, cifs_sb->local_nls,
371 cifs_sb->mnt_cifs_flags & 435 cifs_sb->mnt_cifs_flags &
372 CIFS_MOUNT_MAP_SPECIAL_CHR); 436 CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -431,6 +495,47 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
431 fattr->cf_gid = cifs_sb->mnt_gid; 495 fattr->cf_gid = cifs_sb->mnt_gid;
432} 496}
433 497
498int cifs_get_file_info(struct file *filp)
499{
500 int rc;
501 int xid;
502 FILE_ALL_INFO find_data;
503 struct cifs_fattr fattr;
504 struct inode *inode = filp->f_path.dentry->d_inode;
505 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
506 struct cifsTconInfo *tcon = cifs_sb->tcon;
507 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
508
509 xid = GetXid();
510 rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data);
511 if (rc == -EOPNOTSUPP || rc == -EINVAL) {
512 /*
513 * FIXME: legacy server -- fall back to path-based call?
514 * for now, just skip revalidating and mark inode for
515 * immediate reval.
516 */
517 rc = 0;
518 CIFS_I(inode)->time = 0;
519 goto cgfi_exit;
520 } else if (rc == -EREMOTE) {
521 cifs_create_dfs_fattr(&fattr, inode->i_sb);
522 rc = 0;
523 } else if (rc)
524 goto cgfi_exit;
525
526 /*
527 * don't bother with SFU junk here -- just mark inode as needing
528 * revalidation.
529 */
530 cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false);
531 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
532 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
533 cifs_fattr_to_inode(inode, &fattr);
534cgfi_exit:
535 FreeXid(xid);
536 return rc;
537}
538
434int cifs_get_inode_info(struct inode **pinode, 539int cifs_get_inode_info(struct inode **pinode,
435 const unsigned char *full_path, FILE_ALL_INFO *pfindData, 540 const unsigned char *full_path, FILE_ALL_INFO *pfindData,
436 struct super_block *sb, int xid, const __u16 *pfid) 541 struct super_block *sb, int xid, const __u16 *pfid)
@@ -610,6 +715,16 @@ cifs_find_inode(struct inode *inode, void *opaque)
610 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) 715 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
611 return 0; 716 return 0;
612 717
718 /*
719 * uh oh -- it's a directory. We can't use it since hardlinked dirs are
720 * verboten. Disable serverino and return it as if it were found, the
721 * caller can discard it, generate a uniqueid and retry the find
722 */
723 if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry)) {
724 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
725 cifs_autodisable_serverino(CIFS_SB(inode->i_sb));
726 }
727
613 return 1; 728 return 1;
614} 729}
615 730
@@ -629,15 +744,22 @@ cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
629 unsigned long hash; 744 unsigned long hash;
630 struct inode *inode; 745 struct inode *inode;
631 746
747retry_iget5_locked:
632 cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid)); 748 cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid));
633 749
634 /* hash down to 32-bits on 32-bit arch */ 750 /* hash down to 32-bits on 32-bit arch */
635 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); 751 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
636 752
637 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); 753 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
638
639 /* we have fattrs in hand, update the inode */
640 if (inode) { 754 if (inode) {
755 /* was there a problematic inode number collision? */
756 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
757 iput(inode);
758 fattr->cf_uniqueid = iunique(sb, ROOT_I);
759 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
760 goto retry_iget5_locked;
761 }
762
641 cifs_fattr_to_inode(inode, fattr); 763 cifs_fattr_to_inode(inode, fattr);
642 if (sb->s_flags & MS_NOATIME) 764 if (sb->s_flags & MS_NOATIME)
643 inode->i_flags |= S_NOATIME | S_NOCMTIME; 765 inode->i_flags |= S_NOATIME | S_NOCMTIME;
@@ -914,8 +1036,8 @@ undo_setattr:
914/* 1036/*
915 * If dentry->d_inode is null (usually meaning the cached dentry 1037 * If dentry->d_inode is null (usually meaning the cached dentry
916 * is a negative dentry) then we would attempt a standard SMB delete, but 1038 * is a negative dentry) then we would attempt a standard SMB delete, but
917 * if that fails we can not attempt the fall back mechanisms on EACESS 1039 * if that fails we can not attempt the fall back mechanisms on EACCESS
918 * but will return the EACESS to the caller. Note that the VFS does not call 1040 * but will return the EACCESS to the caller. Note that the VFS does not call
919 * unlink on negative dentries currently. 1041 * unlink on negative dentries currently.
920 */ 1042 */
921int cifs_unlink(struct inode *dir, struct dentry *dentry) 1043int cifs_unlink(struct inode *dir, struct dentry *dentry)
@@ -1388,135 +1510,103 @@ cifs_rename_exit:
1388 return rc; 1510 return rc;
1389} 1511}
1390 1512
1391int cifs_revalidate(struct dentry *direntry) 1513static bool
1514cifs_inode_needs_reval(struct inode *inode)
1392{ 1515{
1393 int xid; 1516 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
1394 int rc = 0, wbrc = 0;
1395 char *full_path;
1396 struct cifs_sb_info *cifs_sb;
1397 struct cifsInodeInfo *cifsInode;
1398 loff_t local_size;
1399 struct timespec local_mtime;
1400 bool invalidate_inode = false;
1401 1517
1402 if (direntry->d_inode == NULL) 1518 if (cifs_i->clientCanCacheRead)
1403 return -ENOENT; 1519 return false;
1404 1520
1405 cifsInode = CIFS_I(direntry->d_inode); 1521 if (!lookupCacheEnabled)
1522 return true;
1406 1523
1407 if (cifsInode == NULL) 1524 if (cifs_i->time == 0)
1408 return -ENOENT; 1525 return true;
1409 1526
1410 /* no sense revalidating inode info on file that no one can write */ 1527 /* FIXME: the actimeo should be tunable */
1411 if (CIFS_I(direntry->d_inode)->clientCanCacheRead) 1528 if (time_after_eq(jiffies, cifs_i->time + HZ))
1412 return rc; 1529 return true;
1530
1531 return false;
1532}
1533
1534/* check invalid_mapping flag and zap the cache if it's set */
1535static void
1536cifs_invalidate_mapping(struct inode *inode)
1537{
1538 int rc;
1539 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
1540
1541 cifs_i->invalid_mapping = false;
1542
1543 /* write back any cached data */
1544 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
1545 rc = filemap_write_and_wait(inode->i_mapping);
1546 if (rc)
1547 cifs_i->write_behind_rc = rc;
1548 }
1549 invalidate_remote_inode(inode);
1550}
1551
1552int cifs_revalidate_file(struct file *filp)
1553{
1554 int rc = 0;
1555 struct inode *inode = filp->f_path.dentry->d_inode;
1556
1557 if (!cifs_inode_needs_reval(inode))
1558 goto check_inval;
1559
1560 if (CIFS_SB(inode->i_sb)->tcon->unix_ext)
1561 rc = cifs_get_file_info_unix(filp);
1562 else
1563 rc = cifs_get_file_info(filp);
1564
1565check_inval:
1566 if (CIFS_I(inode)->invalid_mapping)
1567 cifs_invalidate_mapping(inode);
1568
1569 return rc;
1570}
1571
1572/* revalidate a dentry's inode attributes */
1573int cifs_revalidate_dentry(struct dentry *dentry)
1574{
1575 int xid;
1576 int rc = 0;
1577 char *full_path = NULL;
1578 struct inode *inode = dentry->d_inode;
1579 struct super_block *sb = dentry->d_sb;
1580
1581 if (inode == NULL)
1582 return -ENOENT;
1413 1583
1414 xid = GetXid(); 1584 xid = GetXid();
1415 1585
1416 cifs_sb = CIFS_SB(direntry->d_sb); 1586 if (!cifs_inode_needs_reval(inode))
1587 goto check_inval;
1417 1588
1418 /* can not safely grab the rename sem here if rename calls revalidate 1589 /* can not safely grab the rename sem here if rename calls revalidate
1419 since that would deadlock */ 1590 since that would deadlock */
1420 full_path = build_path_from_dentry(direntry); 1591 full_path = build_path_from_dentry(dentry);
1421 if (full_path == NULL) { 1592 if (full_path == NULL) {
1422 rc = -ENOMEM; 1593 rc = -ENOMEM;
1423 FreeXid(xid); 1594 goto check_inval;
1424 return rc;
1425 }
1426 cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
1427 "jiffies %ld", full_path, direntry->d_inode,
1428 direntry->d_inode->i_count.counter, direntry,
1429 direntry->d_time, jiffies));
1430
1431 if (cifsInode->time == 0) {
1432 /* was set to zero previously to force revalidate */
1433 } else if (time_before(jiffies, cifsInode->time + HZ) &&
1434 lookupCacheEnabled) {
1435 if ((S_ISREG(direntry->d_inode->i_mode) == 0) ||
1436 (direntry->d_inode->i_nlink == 1)) {
1437 kfree(full_path);
1438 FreeXid(xid);
1439 return rc;
1440 } else {
1441 cFYI(1, ("Have to revalidate file due to hardlinks"));
1442 }
1443 }
1444
1445 /* save mtime and size */
1446 local_mtime = direntry->d_inode->i_mtime;
1447 local_size = direntry->d_inode->i_size;
1448
1449 if (cifs_sb->tcon->unix_ext) {
1450 rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
1451 direntry->d_sb, xid);
1452 if (rc) {
1453 cFYI(1, ("error on getting revalidate info %d", rc));
1454/* if (rc != -ENOENT)
1455 rc = 0; */ /* BB should we cache info on
1456 certain errors? */
1457 }
1458 } else {
1459 rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
1460 direntry->d_sb, xid, NULL);
1461 if (rc) {
1462 cFYI(1, ("error on getting revalidate info %d", rc));
1463/* if (rc != -ENOENT)
1464 rc = 0; */ /* BB should we cache info on
1465 certain errors? */
1466 }
1467 } 1595 }
1468 /* should we remap certain errors, access denied?, to zero */
1469 1596
1470 /* if not oplocked, we invalidate inode pages if mtime or file size 1597 cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
1471 had changed on server */ 1598 "jiffies %ld", full_path, inode, inode->i_count.counter,
1599 dentry, dentry->d_time, jiffies));
1472 1600
1473 if (timespec_equal(&local_mtime, &direntry->d_inode->i_mtime) && 1601 if (CIFS_SB(sb)->tcon->unix_ext)
1474 (local_size == direntry->d_inode->i_size)) { 1602 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
1475 cFYI(1, ("cifs_revalidate - inode unchanged")); 1603 else
1476 } else { 1604 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
1477 /* file may have changed on server */ 1605 xid, NULL);
1478 if (cifsInode->clientCanCacheRead) {
1479 /* no need to invalidate inode pages since we were the
1480 only ones who could have modified the file and the
1481 server copy is staler than ours */
1482 } else {
1483 invalidate_inode = true;
1484 }
1485 }
1486 1606
1487 /* can not grab this sem since kernel filesys locking documentation 1607check_inval:
1488 indicates i_mutex may be taken by the kernel on lookup and rename 1608 if (CIFS_I(inode)->invalid_mapping)
1489 which could deadlock if we grab the i_mutex here as well */ 1609 cifs_invalidate_mapping(inode);
1490/* mutex_lock(&direntry->d_inode->i_mutex);*/
1491 /* need to write out dirty pages here */
1492 if (direntry->d_inode->i_mapping) {
1493 /* do we need to lock inode until after invalidate completes
1494 below? */
1495 wbrc = filemap_fdatawrite(direntry->d_inode->i_mapping);
1496 if (wbrc)
1497 CIFS_I(direntry->d_inode)->write_behind_rc = wbrc;
1498 }
1499 if (invalidate_inode) {
1500 /* shrink_dcache not necessary now that cifs dentry ops
1501 are exported for negative dentries */
1502/* if (S_ISDIR(direntry->d_inode->i_mode))
1503 shrink_dcache_parent(direntry); */
1504 if (S_ISREG(direntry->d_inode->i_mode)) {
1505 if (direntry->d_inode->i_mapping) {
1506 wbrc = filemap_fdatawait(direntry->d_inode->i_mapping);
1507 if (wbrc)
1508 CIFS_I(direntry->d_inode)->write_behind_rc = wbrc;
1509 }
1510 /* may eventually have to do this for open files too */
1511 if (list_empty(&(cifsInode->openFileList))) {
1512 /* changed on server - flush read ahead pages */
1513 cFYI(1, ("Invalidating read ahead data on "
1514 "closed file"));
1515 invalidate_remote_inode(direntry->d_inode);
1516 }
1517 }
1518 }
1519/* mutex_unlock(&direntry->d_inode->i_mutex); */
1520 1610
1521 kfree(full_path); 1611 kfree(full_path);
1522 FreeXid(xid); 1612 FreeXid(xid);
@@ -1526,7 +1616,7 @@ int cifs_revalidate(struct dentry *direntry)
1526int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, 1616int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1527 struct kstat *stat) 1617 struct kstat *stat)
1528{ 1618{
1529 int err = cifs_revalidate(dentry); 1619 int err = cifs_revalidate_dentry(dentry);
1530 if (!err) { 1620 if (!err) {
1531 generic_fillattr(dentry->d_inode, stat); 1621 generic_fillattr(dentry->d_inode, stat);
1532 stat->blksize = CIFS_MAX_MSGSIZE; 1622 stat->blksize = CIFS_MAX_MSGSIZE;
@@ -1762,8 +1852,18 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1762 CIFS_MOUNT_MAP_SPECIAL_CHR); 1852 CIFS_MOUNT_MAP_SPECIAL_CHR);
1763 } 1853 }
1764 1854
1765 if (!rc) 1855 if (!rc) {
1766 rc = inode_setattr(inode, attrs); 1856 rc = inode_setattr(inode, attrs);
1857
1858 /* force revalidate when any of these times are set since some
1859 of the fs types (eg ext3, fat) do not have fine enough
1860 time granularity to match protocol, and we do not have a
1861 a way (yet) to query the server fs's time granularity (and
1862 whether it rounds times down).
1863 */
1864 if (!rc && (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME)))
1865 cifsInode->time = 0;
1866 }
1767out: 1867out:
1768 kfree(args); 1868 kfree(args);
1769 kfree(full_path); 1869 kfree(full_path);
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index fc1e0487eaee..c1a9d4236a8c 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -20,6 +20,7 @@
20 */ 20 */
21#include <linux/fs.h> 21#include <linux/fs.h>
22#include <linux/stat.h> 22#include <linux/stat.h>
23#include <linux/slab.h>
23#include <linux/namei.h> 24#include <linux/namei.h>
24#include "cifsfs.h" 25#include "cifsfs.h"
25#include "cifspdu.h" 26#include "cifspdu.h"
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index d27d4ec6579b..d1474996a812 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -79,7 +79,7 @@ sesInfoAlloc(void)
79 ++ret_buf->ses_count; 79 ++ret_buf->ses_count;
80 INIT_LIST_HEAD(&ret_buf->smb_ses_list); 80 INIT_LIST_HEAD(&ret_buf->smb_ses_list);
81 INIT_LIST_HEAD(&ret_buf->tcon_list); 81 INIT_LIST_HEAD(&ret_buf->tcon_list);
82 init_MUTEX(&ret_buf->sesSem); 82 mutex_init(&ret_buf->session_mutex);
83 } 83 }
84 return ret_buf; 84 return ret_buf;
85} 85}
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index f84062f9a985..18e0bc1fb593 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -22,6 +22,7 @@
22 */ 22 */
23#include <linux/fs.h> 23#include <linux/fs.h>
24#include <linux/pagemap.h> 24#include <linux/pagemap.h>
25#include <linux/slab.h>
25#include <linux/stat.h> 26#include <linux/stat.h>
26#include "cifspdu.h" 27#include "cifspdu.h"
27#include "cifsglob.h" 28#include "cifsglob.h"
@@ -77,6 +78,11 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
77 78
78 cFYI(1, ("For %s", name->name)); 79 cFYI(1, ("For %s", name->name));
79 80
81 if (parent->d_op && parent->d_op->d_hash)
82 parent->d_op->d_hash(parent, name);
83 else
84 name->hash = full_name_hash(name->name, name->len);
85
80 dentry = d_lookup(parent, name); 86 dentry = d_lookup(parent, name);
81 if (dentry) { 87 if (dentry) {
82 /* FIXME: check for inode number changes? */ 88 /* FIXME: check for inode number changes? */
@@ -666,12 +672,11 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
666 min(len, max_len), nlt, 672 min(len, max_len), nlt,
667 cifs_sb->mnt_cifs_flags & 673 cifs_sb->mnt_cifs_flags &
668 CIFS_MOUNT_MAP_SPECIAL_CHR); 674 CIFS_MOUNT_MAP_SPECIAL_CHR);
675 pqst->len -= nls_nullsize(nlt);
669 } else { 676 } else {
670 pqst->name = filename; 677 pqst->name = filename;
671 pqst->len = len; 678 pqst->len = len;
672 } 679 }
673 pqst->hash = full_name_hash(pqst->name, pqst->len);
674/* cFYI(1, ("filldir on %s",pqst->name)); */
675 return rc; 680 return rc;
676} 681}
677 682
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 7085a6275c4c..7c3fd7463f44 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -29,6 +29,7 @@
29#include "ntlmssp.h" 29#include "ntlmssp.h"
30#include "nterr.h" 30#include "nterr.h"
31#include <linux/utsname.h> 31#include <linux/utsname.h>
32#include <linux/slab.h>
32#include "cifs_spnego.h" 33#include "cifs_spnego.h"
33 34
34extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, 35extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
@@ -223,9 +224,9 @@ static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
223 /* null user mount */ 224 /* null user mount */
224 *bcc_ptr = 0; 225 *bcc_ptr = 0;
225 *(bcc_ptr+1) = 0; 226 *(bcc_ptr+1) = 0;
226 } else { /* 300 should be long enough for any conceivable user name */ 227 } else {
227 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName, 228 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName,
228 300, nls_cp); 229 MAX_USERNAME_SIZE, nls_cp);
229 } 230 }
230 bcc_ptr += 2 * bytes_ret; 231 bcc_ptr += 2 * bytes_ret;
231 bcc_ptr += 2; /* account for null termination */ 232 bcc_ptr += 2; /* account for null termination */
@@ -246,11 +247,10 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
246 /* copy user */ 247 /* copy user */
247 if (ses->userName == NULL) { 248 if (ses->userName == NULL) {
248 /* BB what about null user mounts - check that we do this BB */ 249 /* BB what about null user mounts - check that we do this BB */
249 } else { /* 300 should be long enough for any conceivable user name */ 250 } else {
250 strncpy(bcc_ptr, ses->userName, 300); 251 strncpy(bcc_ptr, ses->userName, MAX_USERNAME_SIZE);
251 } 252 }
252 /* BB improve check for overflow */ 253 bcc_ptr += strnlen(ses->userName, MAX_USERNAME_SIZE);
253 bcc_ptr += strnlen(ses->userName, 300);
254 *bcc_ptr = 0; 254 *bcc_ptr = 0;
255 bcc_ptr++; /* account for null termination */ 255 bcc_ptr++; /* account for null termination */
256 256
diff --git a/fs/cifs/smbdes.c b/fs/cifs/smbdes.c
index 224a1f478966..b6b6dcb500bf 100644
--- a/fs/cifs/smbdes.c
+++ b/fs/cifs/smbdes.c
@@ -371,7 +371,7 @@ E_P24(unsigned char *p21, const unsigned char *c8, unsigned char *p24)
371 smbhash(p24 + 16, c8, p21 + 14, 1); 371 smbhash(p24 + 16, c8, p21 + 14, 1);
372} 372}
373 373
374#if 0 /* currently unsued */ 374#if 0 /* currently unused */
375static void 375static void
376D_P16(unsigned char *p14, unsigned char *in, unsigned char *out) 376D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
377{ 377{
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index 93fb09a99c69..192ea51af20f 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -24,6 +24,7 @@
24*/ 24*/
25 25
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/slab.h>
27#include <linux/fs.h> 28#include <linux/fs.h>
28#include <linux/string.h> 29#include <linux/string.h>
29#include <linux/kernel.h> 30#include <linux/kernel.h>
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 07b8e71544ee..ad081fe7eb18 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -22,6 +22,7 @@
22 22
23#include <linux/fs.h> 23#include <linux/fs.h>
24#include <linux/list.h> 24#include <linux/list.h>
25#include <linux/gfp.h>
25#include <linux/wait.h> 26#include <linux/wait.h>
26#include <linux/net.h> 27#include <linux/net.h>
27#include <linux/delay.h> 28#include <linux/delay.h>
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index a75afa3dd9e1..f555ce077d4f 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -21,6 +21,7 @@
21 21
22#include <linux/fs.h> 22#include <linux/fs.h>
23#include <linux/posix_acl_xattr.h> 23#include <linux/posix_acl_xattr.h>
24#include <linux/slab.h>
24#include "cifsfs.h" 25#include "cifsfs.h"
25#include "cifspdu.h" 26#include "cifspdu.h"
26#include "cifsglob.h" 27#include "cifsglob.h"
@@ -244,7 +245,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
244 /* revalidate/getattr then populate from inode */ 245 /* revalidate/getattr then populate from inode */
245 } /* BB add else when above is implemented */ 246 } /* BB add else when above is implemented */
246 ea_name += 5; /* skip past user. prefix */ 247 ea_name += 5; /* skip past user. prefix */
247 rc = CIFSSMBQueryEA(xid, pTcon, full_path, ea_name, ea_value, 248 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,
248 buf_size, cifs_sb->local_nls, 249 buf_size, cifs_sb->local_nls,
249 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 250 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
250 } else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) { 251 } else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) {
@@ -252,7 +253,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
252 goto get_ea_exit; 253 goto get_ea_exit;
253 254
254 ea_name += 4; /* skip past os2. prefix */ 255 ea_name += 4; /* skip past os2. prefix */
255 rc = CIFSSMBQueryEA(xid, pTcon, full_path, ea_name, ea_value, 256 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,
256 buf_size, cifs_sb->local_nls, 257 buf_size, cifs_sb->local_nls,
257 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 258 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
258 } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, 259 } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
@@ -364,8 +365,8 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
364 /* if proc/fs/cifs/streamstoxattr is set then 365 /* if proc/fs/cifs/streamstoxattr is set then
365 search server for EAs or streams to 366 search server for EAs or streams to
366 returns as xattrs */ 367 returns as xattrs */
367 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, data, buf_size, 368 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, NULL, data,
368 cifs_sb->local_nls, 369 buf_size, cifs_sb->local_nls,
369 cifs_sb->mnt_cifs_flags & 370 cifs_sb->mnt_cifs_flags &
370 CIFS_MOUNT_MAP_SPECIAL_CHR); 371 CIFS_MOUNT_MAP_SPECIAL_CHR);
371 372