aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/CHANGES10
-rw-r--r--fs/cifs/README25
-rw-r--r--fs/cifs/cifs_dfs_ref.c12
-rw-r--r--fs/cifs/cifs_spnego.c2
-rw-r--r--fs/cifs/cifs_unicode.c2
-rw-r--r--fs/cifs/cifsacl.c4
-rw-r--r--fs/cifs/cifsencrypt.c1
-rw-r--r--fs/cifs/cifsfs.c26
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsglob.h21
-rw-r--r--fs/cifs/cifssmb.c316
-rw-r--r--fs/cifs/connect.c112
-rw-r--r--fs/cifs/dir.c2
-rw-r--r--fs/cifs/file.c43
-rw-r--r--fs/cifs/inode.c15
-rw-r--r--fs/cifs/transport.c17
16 files changed, 305 insertions, 305 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 92888aa90749..145540a316ab 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,13 @@
1Version 1.60
2-------------
3Fix memory leak in reconnect. Fix oops in DFS mount error path.
4Set s_maxbytes to smaller (the max that vfs can handle) so that
5sendfile will now work over cifs mounts again. Add noforcegid
6and noforceuid mount parameters. Fix small mem leak when using
7ntlmv2. Fix 2nd mount to same server but with different port to
8be allowed (rather than reusing the 1st port) - only when the
9user explicitly overrides the port on the 2nd mount.
10
1Version 1.59 11Version 1.59
2------------ 12------------
3Client uses server inode numbers (which are persistent) rather than 13Client uses server inode numbers (which are persistent) rather than
diff --git a/fs/cifs/README b/fs/cifs/README
index ad92921dbde4..79c1a93400be 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -262,11 +262,11 @@ A partial list of the supported mount options follows:
262 mount. 262 mount.
263 domain Set the SMB/CIFS workgroup name prepended to the 263 domain Set the SMB/CIFS workgroup name prepended to the
264 username during CIFS session establishment 264 username during CIFS session establishment
265 forceuid Set the default uid for inodes based on the uid 265 forceuid Set the default uid for inodes to the uid
266 passed in. For mounts to servers 266 passed in on mount. For mounts to servers
267 which do support the CIFS Unix extensions, such as a 267 which do support the CIFS Unix extensions, such as a
268 properly configured Samba server, the server provides 268 properly configured Samba server, the server provides
269 the uid, gid and mode so this parameter should not be 269 the uid, gid and mode so this parameter should not be
270 specified unless the server and clients uid and gid 270 specified unless the server and clients uid and gid
271 numbering differ. If the server and client are in the 271 numbering differ. If the server and client are in the
272 same domain (e.g. running winbind or nss_ldap) and 272 same domain (e.g. running winbind or nss_ldap) and
@@ -278,11 +278,7 @@ A partial list of the supported mount options follows:
278 of existing files will be the uid (gid) of the person 278 of existing files will be the uid (gid) of the person
279 who executed the mount (root, except when mount.cifs 279 who executed the mount (root, except when mount.cifs
280 is configured setuid for user mounts) unless the "uid=" 280 is configured setuid for user mounts) unless the "uid="
281 (gid) mount option is specified. For the uid (gid) of newly 281 (gid) mount option is specified. Also note that permission
282 created files and directories, ie files created since
283 the last mount of the server share, the expected uid
284 (gid) is cached as long as the inode remains in
285 memory on the client. Also note that permission
286 checks (authorization checks) on accesses to a file occur 282 checks (authorization checks) on accesses to a file occur
287 at the server, but there are cases in which an administrator 283 at the server, but there are cases in which an administrator
288 may want to restrict at the client as well. For those 284 may want to restrict at the client as well. For those
@@ -290,12 +286,15 @@ A partial list of the supported mount options follows:
290 (such as Windows), permissions can also be checked at the 286 (such as Windows), permissions can also be checked at the
291 client, and a crude form of client side permission checking 287 client, and a crude form of client side permission checking
292 can be enabled by specifying file_mode and dir_mode on 288 can be enabled by specifying file_mode and dir_mode on
293 the client. Note that the mount.cifs helper must be 289 the client. (default)
294 at version 1.10 or higher to support specifying the uid 290 forcegid (similar to above but for the groupid instead of uid) (default)
295 (or gid) in non-numeric form. 291 noforceuid Fill in file owner information (uid) by requesting it from
296 forcegid (similar to above but for the groupid instead of uid) 292 the server if possible. With this option, the value given in
293 the uid= option (on mount) will only be used if the server
294 can not support returning uids on inodes.
295 noforcegid (similar to above but for the group owner, gid, instead of uid)
297 uid Set the default uid for inodes, and indicate to the 296 uid Set the default uid for inodes, and indicate to the
298 cifs kernel driver which local user mounted . If the server 297 cifs kernel driver which local user mounted. If the server
299 supports the unix extensions the default uid is 298 supports the unix extensions the default uid is
300 not used to fill in the owner fields of inodes (files) 299 not used to fill in the owner fields of inodes (files)
301 unless the "forceuid" parameter is specified. 300 unless the "forceuid" parameter is specified.
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index 3bb11be8b6a8..606912d8f2a8 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -55,7 +55,7 @@ void cifs_dfs_release_automount_timer(void)
55 * i.e. strips from UNC trailing path that is not part of share 55 * 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 56 * name and fixup missing '\' in the begining of DFS node refferal
57 * if neccessary. 57 * if neccessary.
58 * Returns pointer to share name on success or NULL on error. 58 * Returns pointer to share name on success or ERR_PTR on error.
59 * Caller is responsible for freeing returned string. 59 * Caller is responsible for freeing returned string.
60 */ 60 */
61static char *cifs_get_share_name(const char *node_name) 61static char *cifs_get_share_name(const char *node_name)
@@ -68,7 +68,7 @@ static char *cifs_get_share_name(const char *node_name)
68 UNC = kmalloc(len+2 /*for term null and additional \ if it's missed */, 68 UNC = kmalloc(len+2 /*for term null and additional \ if it's missed */,
69 GFP_KERNEL); 69 GFP_KERNEL);
70 if (!UNC) 70 if (!UNC)
71 return NULL; 71 return ERR_PTR(-ENOMEM);
72 72
73 /* get share name and server name */ 73 /* get share name and server name */
74 if (node_name[1] != '\\') { 74 if (node_name[1] != '\\') {
@@ -87,7 +87,7 @@ static char *cifs_get_share_name(const char *node_name)
87 cERROR(1, ("%s: no server name end in node name: %s", 87 cERROR(1, ("%s: no server name end in node name: %s",
88 __func__, node_name)); 88 __func__, node_name));
89 kfree(UNC); 89 kfree(UNC);
90 return NULL; 90 return ERR_PTR(-EINVAL);
91 } 91 }
92 92
93 /* find sharename end */ 93 /* find sharename end */
@@ -133,6 +133,12 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
133 return ERR_PTR(-EINVAL); 133 return ERR_PTR(-EINVAL);
134 134
135 *devname = cifs_get_share_name(ref->node_name); 135 *devname = cifs_get_share_name(ref->node_name);
136 if (IS_ERR(*devname)) {
137 rc = PTR_ERR(*devname);
138 *devname = NULL;
139 goto compose_mount_options_err;
140 }
141
136 rc = dns_resolve_server_name_to_ip(*devname, &srvIP); 142 rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
137 if (rc != 0) { 143 if (rc != 0) {
138 cERROR(1, ("%s: Failed to resolve server part of %s to IP: %d", 144 cERROR(1, ("%s: Failed to resolve server part of %s to IP: %d",
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
index 051caecf7d67..8ec7736ce954 100644
--- a/fs/cifs/cifs_spnego.c
+++ b/fs/cifs/cifs_spnego.c
@@ -125,7 +125,7 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
125 if (server->addr.sockAddr.sin_family == AF_INET) 125 if (server->addr.sockAddr.sin_family == AF_INET)
126 sprintf(dp, "ip4=%pI4", &server->addr.sockAddr.sin_addr); 126 sprintf(dp, "ip4=%pI4", &server->addr.sockAddr.sin_addr);
127 else if (server->addr.sockAddr.sin_family == AF_INET6) 127 else if (server->addr.sockAddr.sin_family == AF_INET6)
128 sprintf(dp, "ip6=%pi6", &server->addr.sockAddr6.sin6_addr); 128 sprintf(dp, "ip6=%pI6", &server->addr.sockAddr6.sin6_addr);
129 else 129 else
130 goto out; 130 goto out;
131 131
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 60e3c4253de0..714a542cbafc 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -44,7 +44,7 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes,
44 int maxwords = maxbytes / 2; 44 int maxwords = maxbytes / 2;
45 char tmp[NLS_MAX_CHARSET_SIZE]; 45 char tmp[NLS_MAX_CHARSET_SIZE];
46 46
47 for (i = 0; from[i] && i < maxwords; i++) { 47 for (i = 0; i < maxwords && from[i]; i++) {
48 charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp, 48 charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp,
49 NLS_MAX_CHARSET_SIZE); 49 NLS_MAX_CHARSET_SIZE);
50 if (charlen > 0) 50 if (charlen > 0)
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 6941c22398a6..7dfe0842a6f6 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -607,7 +607,7 @@ static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
607 return get_cifs_acl_by_path(cifs_sb, path, pacllen); 607 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
608 608
609 pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen); 609 pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen);
610 atomic_dec(&open_file->wrtPending); 610 cifsFileInfo_put(open_file);
611 return pntsd; 611 return pntsd;
612} 612}
613 613
@@ -665,7 +665,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
665 return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen); 665 return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
666 666
667 rc = set_cifs_acl_by_fid(cifs_sb, open_file->netfid, pnntsd, acllen); 667 rc = set_cifs_acl_by_fid(cifs_sb, open_file->netfid, pnntsd, acllen);
668 atomic_dec(&open_file->wrtPending); 668 cifsFileInfo_put(open_file);
669 return rc; 669 return rc;
670} 670}
671 671
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 7c9809523f42..7efe1745494d 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -373,6 +373,7 @@ calc_exit_2:
373 compare with the NTLM example */ 373 compare with the NTLM example */
374 hmac_md5_final(ses->server->ntlmv2_hash, pctxt); 374 hmac_md5_final(ses->server->ntlmv2_hash, pctxt);
375 375
376 kfree(pctxt);
376 return rc; 377 return rc;
377} 378}
378 379
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 44f30504b82d..3610e9958b4c 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -361,13 +361,10 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
361static int 361static int
362cifs_show_options(struct seq_file *s, struct vfsmount *m) 362cifs_show_options(struct seq_file *s, struct vfsmount *m)
363{ 363{
364 struct cifs_sb_info *cifs_sb; 364 struct cifs_sb_info *cifs_sb = CIFS_SB(m->mnt_sb);
365 struct cifsTconInfo *tcon; 365 struct cifsTconInfo *tcon = cifs_sb->tcon;
366
367 cifs_sb = CIFS_SB(m->mnt_sb);
368 tcon = cifs_sb->tcon;
369 366
370 seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName); 367 seq_printf(s, ",unc=%s", tcon->treeName);
371 if (tcon->ses->userName) 368 if (tcon->ses->userName)
372 seq_printf(s, ",username=%s", tcon->ses->userName); 369 seq_printf(s, ",username=%s", tcon->ses->userName);
373 if (tcon->ses->domainName) 370 if (tcon->ses->domainName)
@@ -376,10 +373,14 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
376 seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); 373 seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
377 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) 374 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
378 seq_printf(s, ",forceuid"); 375 seq_printf(s, ",forceuid");
376 else
377 seq_printf(s, ",noforceuid");
379 378
380 seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); 379 seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
381 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) 380 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
382 seq_printf(s, ",forcegid"); 381 seq_printf(s, ",forcegid");
382 else
383 seq_printf(s, ",noforcegid");
383 384
384 cifs_show_address(s, tcon->ses->server); 385 cifs_show_address(s, tcon->ses->server);
385 386
@@ -985,19 +986,19 @@ static int cifs_oplock_thread(void *dummyarg)
985 if (try_to_freeze()) 986 if (try_to_freeze())
986 continue; 987 continue;
987 988
988 spin_lock(&GlobalMid_Lock); 989 spin_lock(&cifs_oplock_lock);
989 if (list_empty(&GlobalOplock_Q)) { 990 if (list_empty(&cifs_oplock_list)) {
990 spin_unlock(&GlobalMid_Lock); 991 spin_unlock(&cifs_oplock_lock);
991 set_current_state(TASK_INTERRUPTIBLE); 992 set_current_state(TASK_INTERRUPTIBLE);
992 schedule_timeout(39*HZ); 993 schedule_timeout(39*HZ);
993 } else { 994 } else {
994 oplock_item = list_entry(GlobalOplock_Q.next, 995 oplock_item = list_entry(cifs_oplock_list.next,
995 struct oplock_q_entry, qhead); 996 struct oplock_q_entry, qhead);
996 cFYI(1, ("found oplock item to write out")); 997 cFYI(1, ("found oplock item to write out"));
997 pTcon = oplock_item->tcon; 998 pTcon = oplock_item->tcon;
998 inode = oplock_item->pinode; 999 inode = oplock_item->pinode;
999 netfid = oplock_item->netfid; 1000 netfid = oplock_item->netfid;
1000 spin_unlock(&GlobalMid_Lock); 1001 spin_unlock(&cifs_oplock_lock);
1001 DeleteOplockQEntry(oplock_item); 1002 DeleteOplockQEntry(oplock_item);
1002 /* can not grab inode sem here since it would 1003 /* can not grab inode sem here since it would
1003 deadlock when oplock received on delete 1004 deadlock when oplock received on delete
@@ -1054,7 +1055,7 @@ init_cifs(void)
1054 int rc = 0; 1055 int rc = 0;
1055 cifs_proc_init(); 1056 cifs_proc_init();
1056 INIT_LIST_HEAD(&cifs_tcp_ses_list); 1057 INIT_LIST_HEAD(&cifs_tcp_ses_list);
1057 INIT_LIST_HEAD(&GlobalOplock_Q); 1058 INIT_LIST_HEAD(&cifs_oplock_list);
1058#ifdef CONFIG_CIFS_EXPERIMENTAL 1059#ifdef CONFIG_CIFS_EXPERIMENTAL
1059 INIT_LIST_HEAD(&GlobalDnotifyReqList); 1060 INIT_LIST_HEAD(&GlobalDnotifyReqList);
1060 INIT_LIST_HEAD(&GlobalDnotifyRsp_Q); 1061 INIT_LIST_HEAD(&GlobalDnotifyRsp_Q);
@@ -1083,6 +1084,7 @@ init_cifs(void)
1083 rwlock_init(&GlobalSMBSeslock); 1084 rwlock_init(&GlobalSMBSeslock);
1084 rwlock_init(&cifs_tcp_ses_lock); 1085 rwlock_init(&cifs_tcp_ses_lock);
1085 spin_lock_init(&GlobalMid_Lock); 1086 spin_lock_init(&GlobalMid_Lock);
1087 spin_lock_init(&cifs_oplock_lock);
1086 1088
1087 if (cifs_max_pending < 2) { 1089 if (cifs_max_pending < 2) {
1088 cifs_max_pending = 2; 1090 cifs_max_pending = 2;
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 6c170948300d..094325e3f714 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -113,5 +113,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
113extern const struct export_operations cifs_export_ops; 113extern const struct export_operations cifs_export_ops;
114#endif /* EXPERIMENTAL */ 114#endif /* EXPERIMENTAL */
115 115
116#define CIFS_VERSION "1.60" 116#define CIFS_VERSION "1.61"
117#endif /* _CIFSFS_H */ 117#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 6084d6379c03..6cfc81a32703 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -351,11 +351,24 @@ struct cifsFileInfo {
351 bool closePend:1; /* file is marked to close */ 351 bool closePend:1; /* file is marked to close */
352 bool invalidHandle:1; /* file closed via session abend */ 352 bool invalidHandle:1; /* file closed via session abend */
353 bool messageMode:1; /* for pipes: message vs byte mode */ 353 bool messageMode:1; /* for pipes: message vs byte mode */
354 atomic_t wrtPending; /* handle in use - defer close */ 354 atomic_t count; /* reference count */
355 struct mutex fh_mutex; /* prevents reopen race after dead ses*/ 355 struct mutex fh_mutex; /* prevents reopen race after dead ses*/
356 struct cifs_search_info srch_inf; 356 struct cifs_search_info srch_inf;
357}; 357};
358 358
359/* Take a reference on the file private data */
360static inline void cifsFileInfo_get(struct cifsFileInfo *cifs_file)
361{
362 atomic_inc(&cifs_file->count);
363}
364
365/* Release a reference on the file private data */
366static inline void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
367{
368 if (atomic_dec_and_test(&cifs_file->count))
369 kfree(cifs_file);
370}
371
359/* 372/*
360 * One of these for each file inode 373 * One of these for each file inode
361 */ 374 */
@@ -656,7 +669,11 @@ GLOBAL_EXTERN rwlock_t cifs_tcp_ses_lock;
656 */ 669 */
657GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; 670GLOBAL_EXTERN rwlock_t GlobalSMBSeslock;
658 671
659GLOBAL_EXTERN struct list_head GlobalOplock_Q; 672/* Global list of oplocks */
673GLOBAL_EXTERN struct list_head cifs_oplock_list;
674
675/* Protects the cifs_oplock_list */
676GLOBAL_EXTERN spinlock_t cifs_oplock_lock;
660 677
661/* Outstanding dir notify requests */ 678/* Outstanding dir notify requests */
662GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; 679GLOBAL_EXTERN struct list_head GlobalDnotifyReqList;
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 1866bc2927d4..301e307e1279 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -100,110 +100,138 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
100 to this tcon */ 100 to this tcon */
101} 101}
102 102
103/* Allocate and return pointer to an SMB request buffer, and set basic 103/* reconnect the socket, tcon, and smb session if needed */
104 SMB information in the SMB header. If the return code is zero, this
105 function must have filled in request_buf pointer */
106static int 104static int
107small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, 105cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command)
108 void **request_buf)
109{ 106{
110 int rc = 0; 107 int rc = 0;
108 struct cifsSesInfo *ses;
109 struct TCP_Server_Info *server;
110 struct nls_table *nls_codepage;
111 111
112 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so 112 /*
113 check for tcp and smb session status done differently 113 * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
114 for those three - in the calling routine */ 114 * tcp and smb session status done differently for those three - in the
115 if (tcon) { 115 * calling routine
116 if (tcon->tidStatus == CifsExiting) { 116 */
117 /* only tree disconnect, open, and write, 117 if (!tcon)
118 (and ulogoff which does not have tcon) 118 return 0;
119 are allowed as we start force umount */ 119
120 if ((smb_command != SMB_COM_WRITE_ANDX) && 120 ses = tcon->ses;
121 (smb_command != SMB_COM_OPEN_ANDX) && 121 server = ses->server;
122 (smb_command != SMB_COM_TREE_DISCONNECT)) { 122
123 cFYI(1, ("can not send cmd %d while umounting", 123 /*
124 smb_command)); 124 * only tree disconnect, open, and write, (and ulogoff which does not
125 return -ENODEV; 125 * have tcon) are allowed as we start force umount
126 } 126 */
127 if (tcon->tidStatus == CifsExiting) {
128 if (smb_command != SMB_COM_WRITE_ANDX &&
129 smb_command != SMB_COM_OPEN_ANDX &&
130 smb_command != SMB_COM_TREE_DISCONNECT) {
131 cFYI(1, ("can not send cmd %d while umounting",
132 smb_command));
133 return -ENODEV;
127 } 134 }
128 if ((tcon->ses) && (tcon->ses->status != CifsExiting) && 135 }
129 (tcon->ses->server)) {
130 struct nls_table *nls_codepage;
131 /* Give Demultiplex thread up to 10 seconds to
132 reconnect, should be greater than cifs socket
133 timeout which is 7 seconds */
134 while (tcon->ses->server->tcpStatus ==
135 CifsNeedReconnect) {
136 wait_event_interruptible_timeout(tcon->ses->server->response_q,
137 (tcon->ses->server->tcpStatus ==
138 CifsGood), 10 * HZ);
139 if (tcon->ses->server->tcpStatus ==
140 CifsNeedReconnect) {
141 /* on "soft" mounts we wait once */
142 if (!tcon->retry ||
143 (tcon->ses->status == CifsExiting)) {
144 cFYI(1, ("gave up waiting on "
145 "reconnect in smb_init"));
146 return -EHOSTDOWN;
147 } /* else "hard" mount - keep retrying
148 until process is killed or server
149 comes back on-line */
150 } else /* TCP session is reestablished now */
151 break;
152 }
153 136
154 nls_codepage = load_nls_default(); 137 if (ses->status == CifsExiting)
155 /* need to prevent multiple threads trying to 138 return -EIO;
156 simultaneously reconnect the same SMB session */
157 down(&tcon->ses->sesSem);
158 if (tcon->ses->need_reconnect)
159 rc = cifs_setup_session(0, tcon->ses,
160 nls_codepage);
161 if (!rc && (tcon->need_reconnect)) {
162 mark_open_files_invalid(tcon);
163 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
164 tcon, nls_codepage);
165 up(&tcon->ses->sesSem);
166 /* BB FIXME add code to check if wsize needs
167 update due to negotiated smb buffer size
168 shrinking */
169 if (rc == 0) {
170 atomic_inc(&tconInfoReconnectCount);
171 /* tell server Unix caps we support */
172 if (tcon->ses->capabilities & CAP_UNIX)
173 reset_cifs_unix_caps(
174 0 /* no xid */,
175 tcon,
176 NULL /* we do not know sb */,
177 NULL /* no vol info */);
178 }
179 139
180 cFYI(1, ("reconnect tcon rc = %d", rc)); 140 /*
181 /* Removed call to reopen open files here. 141 * Give demultiplex thread up to 10 seconds to reconnect, should be
182 It is safer (and faster) to reopen files 142 * greater than cifs socket timeout which is 7 seconds
183 one at a time as needed in read and write */ 143 */
184 144 while (server->tcpStatus == CifsNeedReconnect) {
185 /* Check if handle based operation so we 145 wait_event_interruptible_timeout(server->response_q,
186 know whether we can continue or not without 146 (server->tcpStatus == CifsGood), 10 * HZ);
187 returning to caller to reset file handle */
188 switch (smb_command) {
189 case SMB_COM_READ_ANDX:
190 case SMB_COM_WRITE_ANDX:
191 case SMB_COM_CLOSE:
192 case SMB_COM_FIND_CLOSE2:
193 case SMB_COM_LOCKING_ANDX: {
194 unload_nls(nls_codepage);
195 return -EAGAIN;
196 }
197 }
198 } else {
199 up(&tcon->ses->sesSem);
200 }
201 unload_nls(nls_codepage);
202 147
203 } else { 148 /* is TCP session is reestablished now ?*/
204 return -EIO; 149 if (server->tcpStatus != CifsNeedReconnect)
150 break;
151
152 /*
153 * on "soft" mounts we wait once. Hard mounts keep
154 * retrying until process is killed or server comes
155 * back on-line
156 */
157 if (!tcon->retry || ses->status == CifsExiting) {
158 cFYI(1, ("gave up waiting on reconnect in smb_init"));
159 return -EHOSTDOWN;
205 } 160 }
206 } 161 }
162
163 if (!ses->need_reconnect && !tcon->need_reconnect)
164 return 0;
165
166 nls_codepage = load_nls_default();
167
168 /*
169 * need to prevent multiple threads trying to simultaneously
170 * reconnect the same SMB session
171 */
172 down(&ses->sesSem);
173 if (ses->need_reconnect)
174 rc = cifs_setup_session(0, ses, nls_codepage);
175
176 /* do we need to reconnect tcon? */
177 if (rc || !tcon->need_reconnect) {
178 up(&ses->sesSem);
179 goto out;
180 }
181
182 mark_open_files_invalid(tcon);
183 rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
184 up(&ses->sesSem);
185 cFYI(1, ("reconnect tcon rc = %d", rc));
186
187 if (rc)
188 goto out;
189
190 /*
191 * FIXME: check if wsize needs updated due to negotiated smb buffer
192 * size shrinking
193 */
194 atomic_inc(&tconInfoReconnectCount);
195
196 /* tell server Unix caps we support */
197 if (ses->capabilities & CAP_UNIX)
198 reset_cifs_unix_caps(0, tcon, NULL, NULL);
199
200 /*
201 * Removed call to reopen open files here. It is safer (and faster) to
202 * reopen files one at a time as needed in read and write.
203 *
204 * FIXME: what about file locks? don't we need to reclaim them ASAP?
205 */
206
207out:
208 /*
209 * Check if handle based operation so we know whether we can continue
210 * or not without returning to caller to reset file handle
211 */
212 switch (smb_command) {
213 case SMB_COM_READ_ANDX:
214 case SMB_COM_WRITE_ANDX:
215 case SMB_COM_CLOSE:
216 case SMB_COM_FIND_CLOSE2:
217 case SMB_COM_LOCKING_ANDX:
218 rc = -EAGAIN;
219 }
220
221 unload_nls(nls_codepage);
222 return rc;
223}
224
225/* Allocate and return pointer to an SMB request buffer, and set basic
226 SMB information in the SMB header. If the return code is zero, this
227 function must have filled in request_buf pointer */
228static int
229small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
230 void **request_buf)
231{
232 int rc = 0;
233
234 rc = cifs_reconnect_tcon(tcon, smb_command);
207 if (rc) 235 if (rc)
208 return rc; 236 return rc;
209 237
@@ -256,101 +284,7 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
256{ 284{
257 int rc = 0; 285 int rc = 0;
258 286
259 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so 287 rc = cifs_reconnect_tcon(tcon, smb_command);
260 check for tcp and smb session status done differently
261 for those three - in the calling routine */
262 if (tcon) {
263 if (tcon->tidStatus == CifsExiting) {
264 /* only tree disconnect, open, and write,
265 (and ulogoff which does not have tcon)
266 are allowed as we start force umount */
267 if ((smb_command != SMB_COM_WRITE_ANDX) &&
268 (smb_command != SMB_COM_OPEN_ANDX) &&
269 (smb_command != SMB_COM_TREE_DISCONNECT)) {
270 cFYI(1, ("can not send cmd %d while umounting",
271 smb_command));
272 return -ENODEV;
273 }
274 }
275
276 if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
277 (tcon->ses->server)) {
278 struct nls_table *nls_codepage;
279 /* Give Demultiplex thread up to 10 seconds to
280 reconnect, should be greater than cifs socket
281 timeout which is 7 seconds */
282 while (tcon->ses->server->tcpStatus ==
283 CifsNeedReconnect) {
284 wait_event_interruptible_timeout(tcon->ses->server->response_q,
285 (tcon->ses->server->tcpStatus ==
286 CifsGood), 10 * HZ);
287 if (tcon->ses->server->tcpStatus ==
288 CifsNeedReconnect) {
289 /* on "soft" mounts we wait once */
290 if (!tcon->retry ||
291 (tcon->ses->status == CifsExiting)) {
292 cFYI(1, ("gave up waiting on "
293 "reconnect in smb_init"));
294 return -EHOSTDOWN;
295 } /* else "hard" mount - keep retrying
296 until process is killed or server
297 comes on-line */
298 } else /* TCP session is reestablished now */
299 break;
300 }
301 nls_codepage = load_nls_default();
302 /* need to prevent multiple threads trying to
303 simultaneously reconnect the same SMB session */
304 down(&tcon->ses->sesSem);
305 if (tcon->ses->need_reconnect)
306 rc = cifs_setup_session(0, tcon->ses,
307 nls_codepage);
308 if (!rc && (tcon->need_reconnect)) {
309 mark_open_files_invalid(tcon);
310 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
311 tcon, nls_codepage);
312 up(&tcon->ses->sesSem);
313 /* BB FIXME add code to check if wsize needs
314 update due to negotiated smb buffer size
315 shrinking */
316 if (rc == 0) {
317 atomic_inc(&tconInfoReconnectCount);
318 /* tell server Unix caps we support */
319 if (tcon->ses->capabilities & CAP_UNIX)
320 reset_cifs_unix_caps(
321 0 /* no xid */,
322 tcon,
323 NULL /* do not know sb */,
324 NULL /* no vol info */);
325 }
326
327 cFYI(1, ("reconnect tcon rc = %d", rc));
328 /* Removed call to reopen open files here.
329 It is safer (and faster) to reopen files
330 one at a time as needed in read and write */
331
332 /* Check if handle based operation so we
333 know whether we can continue or not without
334 returning to caller to reset file handle */
335 switch (smb_command) {
336 case SMB_COM_READ_ANDX:
337 case SMB_COM_WRITE_ANDX:
338 case SMB_COM_CLOSE:
339 case SMB_COM_FIND_CLOSE2:
340 case SMB_COM_LOCKING_ANDX: {
341 unload_nls(nls_codepage);
342 return -EAGAIN;
343 }
344 }
345 } else {
346 up(&tcon->ses->sesSem);
347 }
348 unload_nls(nls_codepage);
349
350 } else {
351 return -EIO;
352 }
353 }
354 if (rc) 288 if (rc)
355 return rc; 289 return rc;
356 290
@@ -3961,6 +3895,10 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
3961 if (is_unicode) { 3895 if (is_unicode) {
3962 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2, 3896 __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
3963 GFP_KERNEL); 3897 GFP_KERNEL);
3898 if (tmp == NULL) {
3899 rc = -ENOMEM;
3900 goto parse_DFS_referrals_exit;
3901 }
3964 cifsConvertToUCS((__le16 *) tmp, searchName, 3902 cifsConvertToUCS((__le16 *) tmp, searchName,
3965 PATH_MAX, nls_codepage, remap); 3903 PATH_MAX, nls_codepage, remap);
3966 node->path_consumed = cifs_ucs2_bytes(tmp, 3904 node->path_consumed = cifs_ucs2_bytes(tmp,
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 9bb5c8750736..d49682433c20 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -803,6 +803,10 @@ cifs_parse_mount_options(char *options, const char *devname,
803 char *data; 803 char *data;
804 unsigned int temp_len, i, j; 804 unsigned int temp_len, i, j;
805 char separator[2]; 805 char separator[2];
806 short int override_uid = -1;
807 short int override_gid = -1;
808 bool uid_specified = false;
809 bool gid_specified = false;
806 810
807 separator[0] = ','; 811 separator[0] = ',';
808 separator[1] = 0; 812 separator[1] = 0;
@@ -1093,18 +1097,20 @@ cifs_parse_mount_options(char *options, const char *devname,
1093 "too long.\n"); 1097 "too long.\n");
1094 return 1; 1098 return 1;
1095 } 1099 }
1096 } else if (strnicmp(data, "uid", 3) == 0) { 1100 } else if (!strnicmp(data, "uid", 3) && value && *value) {
1097 if (value && *value) 1101 vol->linux_uid = simple_strtoul(value, &value, 0);
1098 vol->linux_uid = 1102 uid_specified = true;
1099 simple_strtoul(value, &value, 0); 1103 } else if (!strnicmp(data, "forceuid", 8)) {
1100 } else if (strnicmp(data, "forceuid", 8) == 0) { 1104 override_uid = 1;
1101 vol->override_uid = 1; 1105 } else if (!strnicmp(data, "noforceuid", 10)) {
1102 } else if (strnicmp(data, "gid", 3) == 0) { 1106 override_uid = 0;
1103 if (value && *value) 1107 } else if (!strnicmp(data, "gid", 3) && value && *value) {
1104 vol->linux_gid = 1108 vol->linux_gid = simple_strtoul(value, &value, 0);
1105 simple_strtoul(value, &value, 0); 1109 gid_specified = true;
1106 } else if (strnicmp(data, "forcegid", 8) == 0) { 1110 } else if (!strnicmp(data, "forcegid", 8)) {
1107 vol->override_gid = 1; 1111 override_gid = 1;
1112 } else if (!strnicmp(data, "noforcegid", 10)) {
1113 override_gid = 0;
1108 } else if (strnicmp(data, "file_mode", 4) == 0) { 1114 } else if (strnicmp(data, "file_mode", 4) == 0) {
1109 if (value && *value) { 1115 if (value && *value) {
1110 vol->file_mode = 1116 vol->file_mode =
@@ -1355,11 +1361,23 @@ cifs_parse_mount_options(char *options, const char *devname,
1355 if (vol->UNCip == NULL) 1361 if (vol->UNCip == NULL)
1356 vol->UNCip = &vol->UNC[2]; 1362 vol->UNCip = &vol->UNC[2];
1357 1363
1364 if (uid_specified)
1365 vol->override_uid = override_uid;
1366 else if (override_uid == 1)
1367 printk(KERN_NOTICE "CIFS: ignoring forceuid mount option "
1368 "specified with no uid= option.\n");
1369
1370 if (gid_specified)
1371 vol->override_gid = override_gid;
1372 else if (override_gid == 1)
1373 printk(KERN_NOTICE "CIFS: ignoring forcegid mount option "
1374 "specified with no gid= option.\n");
1375
1358 return 0; 1376 return 0;
1359} 1377}
1360 1378
1361static struct TCP_Server_Info * 1379static struct TCP_Server_Info *
1362cifs_find_tcp_session(struct sockaddr_storage *addr) 1380cifs_find_tcp_session(struct sockaddr_storage *addr, unsigned short int port)
1363{ 1381{
1364 struct list_head *tmp; 1382 struct list_head *tmp;
1365 struct TCP_Server_Info *server; 1383 struct TCP_Server_Info *server;
@@ -1379,16 +1397,37 @@ cifs_find_tcp_session(struct sockaddr_storage *addr)
1379 if (server->tcpStatus == CifsNew) 1397 if (server->tcpStatus == CifsNew)
1380 continue; 1398 continue;
1381 1399
1382 if (addr->ss_family == AF_INET && 1400 switch (addr->ss_family) {
1383 (addr4->sin_addr.s_addr != 1401 case AF_INET:
1384 server->addr.sockAddr.sin_addr.s_addr)) 1402 if (addr4->sin_addr.s_addr ==
1385 continue; 1403 server->addr.sockAddr.sin_addr.s_addr) {
1386 else if (addr->ss_family == AF_INET6 && 1404 addr4->sin_port = htons(port);
1387 (!ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr, 1405 /* user overrode default port? */
1388 &addr6->sin6_addr) || 1406 if (addr4->sin_port) {
1389 server->addr.sockAddr6.sin6_scope_id != 1407 if (addr4->sin_port !=
1390 addr6->sin6_scope_id)) 1408 server->addr.sockAddr.sin_port)
1391 continue; 1409 continue;
1410 }
1411 break;
1412 } else
1413 continue;
1414
1415 case AF_INET6:
1416 if (ipv6_addr_equal(&addr6->sin6_addr,
1417 &server->addr.sockAddr6.sin6_addr) &&
1418 (addr6->sin6_scope_id ==
1419 server->addr.sockAddr6.sin6_scope_id)) {
1420 addr6->sin6_port = htons(port);
1421 /* user overrode default port? */
1422 if (addr6->sin6_port) {
1423 if (addr6->sin6_port !=
1424 server->addr.sockAddr6.sin6_port)
1425 continue;
1426 }
1427 break;
1428 } else
1429 continue;
1430 }
1392 1431
1393 ++server->srv_count; 1432 ++server->srv_count;
1394 write_unlock(&cifs_tcp_ses_lock); 1433 write_unlock(&cifs_tcp_ses_lock);
@@ -1457,7 +1496,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
1457 } 1496 }
1458 1497
1459 /* see if we already have a matching tcp_ses */ 1498 /* see if we already have a matching tcp_ses */
1460 tcp_ses = cifs_find_tcp_session(&addr); 1499 tcp_ses = cifs_find_tcp_session(&addr, volume_info->port);
1461 if (tcp_ses) 1500 if (tcp_ses)
1462 return tcp_ses; 1501 return tcp_ses;
1463 1502
@@ -2452,10 +2491,10 @@ try_mount_again:
2452 tcon->local_lease = volume_info->local_lease; 2491 tcon->local_lease = volume_info->local_lease;
2453 } 2492 }
2454 if (pSesInfo) { 2493 if (pSesInfo) {
2455 if (pSesInfo->capabilities & CAP_LARGE_FILES) { 2494 if (pSesInfo->capabilities & CAP_LARGE_FILES)
2456 sb->s_maxbytes = (u64) 1 << 63; 2495 sb->s_maxbytes = MAX_LFS_FILESIZE;
2457 } else 2496 else
2458 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */ 2497 sb->s_maxbytes = MAX_NON_LFS;
2459 } 2498 }
2460 2499
2461 /* BB FIXME fix time_gran to be larger for LANMAN sessions */ 2500 /* BB FIXME fix time_gran to be larger for LANMAN sessions */
@@ -2544,11 +2583,20 @@ remote_path_check:
2544 2583
2545 if (mount_data != mount_data_global) 2584 if (mount_data != mount_data_global)
2546 kfree(mount_data); 2585 kfree(mount_data);
2586
2547 mount_data = cifs_compose_mount_options( 2587 mount_data = cifs_compose_mount_options(
2548 cifs_sb->mountdata, full_path + 1, 2588 cifs_sb->mountdata, full_path + 1,
2549 referrals, &fake_devname); 2589 referrals, &fake_devname);
2550 kfree(fake_devname); 2590
2551 free_dfs_info_array(referrals, num_referrals); 2591 free_dfs_info_array(referrals, num_referrals);
2592 kfree(fake_devname);
2593 kfree(full_path);
2594
2595 if (IS_ERR(mount_data)) {
2596 rc = PTR_ERR(mount_data);
2597 mount_data = NULL;
2598 goto mount_fail_check;
2599 }
2552 2600
2553 if (tcon) 2601 if (tcon)
2554 cifs_put_tcon(tcon); 2602 cifs_put_tcon(tcon);
@@ -2556,8 +2604,6 @@ remote_path_check:
2556 cifs_put_smb_ses(pSesInfo); 2604 cifs_put_smb_ses(pSesInfo);
2557 2605
2558 cleanup_volume_info(&volume_info); 2606 cleanup_volume_info(&volume_info);
2559 FreeXid(xid);
2560 kfree(full_path);
2561 referral_walks_count++; 2607 referral_walks_count++;
2562 goto try_mount_again; 2608 goto try_mount_again;
2563 } 2609 }
@@ -2611,9 +2657,9 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2611 return -EIO; 2657 return -EIO;
2612 2658
2613 smb_buffer = cifs_buf_get(); 2659 smb_buffer = cifs_buf_get();
2614 if (smb_buffer == NULL) { 2660 if (smb_buffer == NULL)
2615 return -ENOMEM; 2661 return -ENOMEM;
2616 } 2662
2617 smb_buffer_response = smb_buffer; 2663 smb_buffer_response = smb_buffer;
2618 2664
2619 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX, 2665 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 4326ffd90fa9..a6424cfc0121 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -153,7 +153,7 @@ cifs_fill_fileinfo(struct inode *newinode, __u16 fileHandle,
153 mutex_init(&pCifsFile->fh_mutex); 153 mutex_init(&pCifsFile->fh_mutex);
154 mutex_init(&pCifsFile->lock_mutex); 154 mutex_init(&pCifsFile->lock_mutex);
155 INIT_LIST_HEAD(&pCifsFile->llist); 155 INIT_LIST_HEAD(&pCifsFile->llist);
156 atomic_set(&pCifsFile->wrtPending, 0); 156 atomic_set(&pCifsFile->count, 1);
157 157
158 /* set the following in open now 158 /* set the following in open now
159 pCifsFile->pfile = file; */ 159 pCifsFile->pfile = file; */
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index c34b7f8a217b..fa7beac8b80e 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -53,11 +53,9 @@ static inline struct cifsFileInfo *cifs_init_private(
53 private_data->pInode = inode; 53 private_data->pInode = inode;
54 private_data->invalidHandle = false; 54 private_data->invalidHandle = false;
55 private_data->closePend = false; 55 private_data->closePend = false;
56 /* we have to track num writers to the inode, since writepages 56 /* Initialize reference count to one. The private data is
57 does not tell us which handle the write is for so there can 57 freed on the release of the last reference */
58 be a close (overlapping with write) of the filehandle that 58 atomic_set(&private_data->count, 1);
59 cifs_writepages chose to use */
60 atomic_set(&private_data->wrtPending, 0);
61 59
62 return private_data; 60 return private_data;
63} 61}
@@ -643,7 +641,7 @@ int cifs_close(struct inode *inode, struct file *file)
643 if (!pTcon->need_reconnect) { 641 if (!pTcon->need_reconnect) {
644 write_unlock(&GlobalSMBSeslock); 642 write_unlock(&GlobalSMBSeslock);
645 timeout = 2; 643 timeout = 2;
646 while ((atomic_read(&pSMBFile->wrtPending) != 0) 644 while ((atomic_read(&pSMBFile->count) != 1)
647 && (timeout <= 2048)) { 645 && (timeout <= 2048)) {
648 /* Give write a better chance to get to 646 /* Give write a better chance to get to
649 server ahead of the close. We do not 647 server ahead of the close. We do not
@@ -657,8 +655,6 @@ int cifs_close(struct inode *inode, struct file *file)
657 msleep(timeout); 655 msleep(timeout);
658 timeout *= 4; 656 timeout *= 4;
659 } 657 }
660 if (atomic_read(&pSMBFile->wrtPending))
661 cERROR(1, ("close with pending write"));
662 if (!pTcon->need_reconnect && 658 if (!pTcon->need_reconnect &&
663 !pSMBFile->invalidHandle) 659 !pSMBFile->invalidHandle)
664 rc = CIFSSMBClose(xid, pTcon, 660 rc = CIFSSMBClose(xid, pTcon,
@@ -681,24 +677,7 @@ int cifs_close(struct inode *inode, struct file *file)
681 list_del(&pSMBFile->flist); 677 list_del(&pSMBFile->flist);
682 list_del(&pSMBFile->tlist); 678 list_del(&pSMBFile->tlist);
683 write_unlock(&GlobalSMBSeslock); 679 write_unlock(&GlobalSMBSeslock);
684 timeout = 10; 680 cifsFileInfo_put(file->private_data);
685 /* We waited above to give the SMBWrite a chance to issue
686 on the wire (so we do not get SMBWrite returning EBADF
687 if writepages is racing with close. Note that writepages
688 does not specify a file handle, so it is possible for a file
689 to be opened twice, and the application close the "wrong"
690 file handle - in these cases we delay long enough to allow
691 the SMBWrite to get on the wire before the SMB Close.
692 We allow total wait here over 45 seconds, more than
693 oplock break time, and more than enough to allow any write
694 to complete on the server, or to time out on the client */
695 while ((atomic_read(&pSMBFile->wrtPending) != 0)
696 && (timeout <= 50000)) {
697 cERROR(1, ("writes pending, delay free of handle"));
698 msleep(timeout);
699 timeout *= 8;
700 }
701 kfree(file->private_data);
702 file->private_data = NULL; 681 file->private_data = NULL;
703 } else 682 } else
704 rc = -EBADF; 683 rc = -EBADF;
@@ -1236,7 +1215,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
1236 if (!open_file->invalidHandle) { 1215 if (!open_file->invalidHandle) {
1237 /* found a good file */ 1216 /* found a good file */
1238 /* lock it so it will not be closed on us */ 1217 /* lock it so it will not be closed on us */
1239 atomic_inc(&open_file->wrtPending); 1218 cifsFileInfo_get(open_file);
1240 read_unlock(&GlobalSMBSeslock); 1219 read_unlock(&GlobalSMBSeslock);
1241 return open_file; 1220 return open_file;
1242 } /* else might as well continue, and look for 1221 } /* else might as well continue, and look for
@@ -1276,7 +1255,7 @@ refind_writable:
1276 if (open_file->pfile && 1255 if (open_file->pfile &&
1277 ((open_file->pfile->f_flags & O_RDWR) || 1256 ((open_file->pfile->f_flags & O_RDWR) ||
1278 (open_file->pfile->f_flags & O_WRONLY))) { 1257 (open_file->pfile->f_flags & O_WRONLY))) {
1279 atomic_inc(&open_file->wrtPending); 1258 cifsFileInfo_get(open_file);
1280 1259
1281 if (!open_file->invalidHandle) { 1260 if (!open_file->invalidHandle) {
1282 /* found a good writable file */ 1261 /* found a good writable file */
@@ -1293,7 +1272,7 @@ refind_writable:
1293 else { /* start over in case this was deleted */ 1272 else { /* start over in case this was deleted */
1294 /* since the list could be modified */ 1273 /* since the list could be modified */
1295 read_lock(&GlobalSMBSeslock); 1274 read_lock(&GlobalSMBSeslock);
1296 atomic_dec(&open_file->wrtPending); 1275 cifsFileInfo_put(open_file);
1297 goto refind_writable; 1276 goto refind_writable;
1298 } 1277 }
1299 } 1278 }
@@ -1309,7 +1288,7 @@ refind_writable:
1309 read_lock(&GlobalSMBSeslock); 1288 read_lock(&GlobalSMBSeslock);
1310 /* can not use this handle, no write 1289 /* can not use this handle, no write
1311 pending on this one after all */ 1290 pending on this one after all */
1312 atomic_dec(&open_file->wrtPending); 1291 cifsFileInfo_put(open_file);
1313 1292
1314 if (open_file->closePend) /* list could have changed */ 1293 if (open_file->closePend) /* list could have changed */
1315 goto refind_writable; 1294 goto refind_writable;
@@ -1373,7 +1352,7 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1373 if (open_file) { 1352 if (open_file) {
1374 bytes_written = cifs_write(open_file->pfile, write_data, 1353 bytes_written = cifs_write(open_file->pfile, write_data,
1375 to-from, &offset); 1354 to-from, &offset);
1376 atomic_dec(&open_file->wrtPending); 1355 cifsFileInfo_put(open_file);
1377 /* Does mm or vfs already set times? */ 1356 /* Does mm or vfs already set times? */
1378 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb); 1357 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
1379 if ((bytes_written > 0) && (offset)) 1358 if ((bytes_written > 0) && (offset))
@@ -1562,7 +1541,7 @@ retry:
1562 bytes_to_write, offset, 1541 bytes_to_write, offset,
1563 &bytes_written, iov, n_iov, 1542 &bytes_written, iov, n_iov,
1564 long_op); 1543 long_op);
1565 atomic_dec(&open_file->wrtPending); 1544 cifsFileInfo_put(open_file);
1566 cifs_update_eof(cifsi, offset, bytes_written); 1545 cifs_update_eof(cifsi, offset, bytes_written);
1567 1546
1568 if (rc || bytes_written < bytes_to_write) { 1547 if (rc || bytes_written < bytes_to_write) {
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 18afe57b2461..1f09c7619319 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -212,7 +212,7 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
212 * junction to the new submount (ie to setup the fake directory 212 * junction to the new submount (ie to setup the fake directory
213 * which represents a DFS referral). 213 * which represents a DFS referral).
214 */ 214 */
215void 215static void
216cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) 216cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
217{ 217{
218 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 218 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
@@ -388,7 +388,7 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
388} 388}
389 389
390/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */ 390/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
391void 391static void
392cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, 392cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
393 struct cifs_sb_info *cifs_sb, bool adjust_tz) 393 struct cifs_sb_info *cifs_sb, bool adjust_tz)
394{ 394{
@@ -513,9 +513,12 @@ int cifs_get_inode_info(struct inode **pinode,
513 cifs_sb->mnt_cifs_flags & 513 cifs_sb->mnt_cifs_flags &
514 CIFS_MOUNT_MAP_SPECIAL_CHR); 514 CIFS_MOUNT_MAP_SPECIAL_CHR);
515 if (rc1) { 515 if (rc1) {
516 /* BB EOPNOSUPP disable SERVER_INUM? */
517 cFYI(1, ("GetSrvInodeNum rc %d", rc1)); 516 cFYI(1, ("GetSrvInodeNum rc %d", rc1));
518 fattr.cf_uniqueid = iunique(sb, ROOT_I); 517 fattr.cf_uniqueid = iunique(sb, ROOT_I);
518 /* disable serverino if call not supported */
519 if (rc1 == -EINVAL)
520 cifs_sb->mnt_cifs_flags &=
521 ~CIFS_MOUNT_SERVER_INUM;
519 } 522 }
520 } else { 523 } else {
521 fattr.cf_uniqueid = iunique(sb, ROOT_I); 524 fattr.cf_uniqueid = iunique(sb, ROOT_I);
@@ -797,7 +800,7 @@ set_via_filehandle:
797 if (open_file == NULL) 800 if (open_file == NULL)
798 CIFSSMBClose(xid, pTcon, netfid); 801 CIFSSMBClose(xid, pTcon, netfid);
799 else 802 else
800 atomic_dec(&open_file->wrtPending); 803 cifsFileInfo_put(open_file);
801out: 804out:
802 return rc; 805 return rc;
803} 806}
@@ -1632,7 +1635,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
1632 __u32 npid = open_file->pid; 1635 __u32 npid = open_file->pid;
1633 rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid, 1636 rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid,
1634 npid, false); 1637 npid, false);
1635 atomic_dec(&open_file->wrtPending); 1638 cifsFileInfo_put(open_file);
1636 cFYI(1, ("SetFSize for attrs rc = %d", rc)); 1639 cFYI(1, ("SetFSize for attrs rc = %d", rc));
1637 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { 1640 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1638 unsigned int bytes_written; 1641 unsigned int bytes_written;
@@ -1787,7 +1790,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1787 u16 nfid = open_file->netfid; 1790 u16 nfid = open_file->netfid;
1788 u32 npid = open_file->pid; 1791 u32 npid = open_file->pid;
1789 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); 1792 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
1790 atomic_dec(&open_file->wrtPending); 1793 cifsFileInfo_put(open_file);
1791 } else { 1794 } else {
1792 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, 1795 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
1793 cifs_sb->local_nls, 1796 cifs_sb->local_nls,
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 0ad3e2d116a6..1da4ab250eae 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -119,20 +119,19 @@ AllocOplockQEntry(struct inode *pinode, __u16 fid, struct cifsTconInfo *tcon)
119 temp->pinode = pinode; 119 temp->pinode = pinode;
120 temp->tcon = tcon; 120 temp->tcon = tcon;
121 temp->netfid = fid; 121 temp->netfid = fid;
122 spin_lock(&GlobalMid_Lock); 122 spin_lock(&cifs_oplock_lock);
123 list_add_tail(&temp->qhead, &GlobalOplock_Q); 123 list_add_tail(&temp->qhead, &cifs_oplock_list);
124 spin_unlock(&GlobalMid_Lock); 124 spin_unlock(&cifs_oplock_lock);
125 } 125 }
126 return temp; 126 return temp;
127
128} 127}
129 128
130void DeleteOplockQEntry(struct oplock_q_entry *oplockEntry) 129void DeleteOplockQEntry(struct oplock_q_entry *oplockEntry)
131{ 130{
132 spin_lock(&GlobalMid_Lock); 131 spin_lock(&cifs_oplock_lock);
133 /* should we check if list empty first? */ 132 /* should we check if list empty first? */
134 list_del(&oplockEntry->qhead); 133 list_del(&oplockEntry->qhead);
135 spin_unlock(&GlobalMid_Lock); 134 spin_unlock(&cifs_oplock_lock);
136 kmem_cache_free(cifs_oplock_cachep, oplockEntry); 135 kmem_cache_free(cifs_oplock_cachep, oplockEntry);
137} 136}
138 137
@@ -144,14 +143,14 @@ void DeleteTconOplockQEntries(struct cifsTconInfo *tcon)
144 if (tcon == NULL) 143 if (tcon == NULL)
145 return; 144 return;
146 145
147 spin_lock(&GlobalMid_Lock); 146 spin_lock(&cifs_oplock_lock);
148 list_for_each_entry(temp, &GlobalOplock_Q, qhead) { 147 list_for_each_entry(temp, &cifs_oplock_list, qhead) {
149 if ((temp->tcon) && (temp->tcon == tcon)) { 148 if ((temp->tcon) && (temp->tcon == tcon)) {
150 list_del(&temp->qhead); 149 list_del(&temp->qhead);
151 kmem_cache_free(cifs_oplock_cachep, temp); 150 kmem_cache_free(cifs_oplock_cachep, temp);
152 } 151 }
153 } 152 }
154 spin_unlock(&GlobalMid_Lock); 153 spin_unlock(&cifs_oplock_lock);
155} 154}
156 155
157static int 156static int