Blame view

fs/cifs/connect.c 111 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   *   fs/cifs/connect.c
   *
1080ef758   Steve French   CIFS: Introduce S...
4
   *   Copyright (C) International Business Machines  Corp., 2002,2011
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
8
9
10
11
12
13
14
15
16
17
18
   *   Author(s): Steve French (sfrench@us.ibm.com)
   *
   *   This library is free software; you can redistribute it and/or modify
   *   it under the terms of the GNU Lesser General Public License as published
   *   by the Free Software Foundation; either version 2.1 of the License, or
   *   (at your option) any later version.
   *
   *   This library is distributed in the hope that it will be useful,
   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
   *   the GNU Lesser General Public License for more details.
   *
   *   You should have received a copy of the GNU Lesser General Public License
   *   along with this library; if not, write to the Free Software
fb8c4b14d   Steve French   [CIFS] whitespace...
19
   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
24
25
   */
  #include <linux/fs.h>
  #include <linux/net.h>
  #include <linux/string.h>
  #include <linux/list.h>
  #include <linux/wait.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
26
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
30
  #include <linux/pagemap.h>
  #include <linux/ctype.h>
  #include <linux/utsname.h>
  #include <linux/mempool.h>
b8643e1b5   Steve French   [PATCH] cifs: Do ...
31
  #include <linux/delay.h>
f191401f5   Steve French   [CIFS] rmmod cifs...
32
  #include <linux/completion.h>
aaf737adb   Igor Mammedov   [CIFS] Switch cif...
33
  #include <linux/kthread.h>
0ae0efada   Steve French   [CIFS] Fix rsize ...
34
  #include <linux/pagevec.h>
7dfb71030   Nigel Cunningham   [PATCH] Add inclu...
35
  #include <linux/freezer.h>
5c2503a8e   Igor Mammedov   Added loop check ...
36
  #include <linux/namei.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
  #include <asm/uaccess.h>
  #include <asm/processor.h>
50b64e3b7   Jeff Layton   cifs: fix IPv6 ad...
39
  #include <linux/inet.h>
143cb494c   Paul Gortmaker   fs: add module.h ...
40
  #include <linux/module.h>
8a8798a5f   Jeff Layton   cifs: fetch crede...
41
  #include <keys/user-type.h>
0e2bedaa3   Steve French   [CIFS] ipv6_addr_...
42
  #include <net/ipv6.h>
8830d7e07   Sachin Prabhu   cifs: use standar...
43
  #include <linux/parser.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
45
46
47
48
49
50
51
52
  #include "cifspdu.h"
  #include "cifsglob.h"
  #include "cifsproto.h"
  #include "cifs_unicode.h"
  #include "cifs_debug.h"
  #include "cifs_fs_sb.h"
  #include "ntlmssp.h"
  #include "nterr.h"
  #include "rfc1002pdu.h"
488f1d2d6   Suresh Jayaraman   cifs: define serv...
53
  #include "fscache.h"
48f9526f4   Pavel Shilovsky   CIFS: Fix a possi...
54
55
56
  #ifdef CONFIG_CIFS_SMB2
  #include "smb2proto.h"
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
58
59
  
  #define CIFS_PORT 445
  #define RFC1001_PORT 139
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
  extern mempool_t *cifs_req_poolp;
2de970ff6   Jeff Layton   cifs: implement r...
61
  /* FIXME: should these be tunable? */
9d002df49   Jeff Layton   cifs: add routine...
62
  #define TLINK_ERROR_EXPIRE	(1 * HZ)
2de970ff6   Jeff Layton   cifs: implement r...
63
  #define TLINK_IDLE_EXPIRE	(600 * HZ)
9d002df49   Jeff Layton   cifs: add routine...
64

8830d7e07   Sachin Prabhu   cifs: use standar...
65
  enum {
8830d7e07   Sachin Prabhu   cifs: use standar...
66
67
68
  	/* Mount options that take no arguments */
  	Opt_user_xattr, Opt_nouser_xattr,
  	Opt_forceuid, Opt_noforceuid,
72bd481f8   Jeff Layton   cifs: reinstate t...
69
  	Opt_forcegid, Opt_noforcegid,
8830d7e07   Sachin Prabhu   cifs: use standar...
70
71
  	Opt_noblocksend, Opt_noautotune,
  	Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
2baa26825   Steve French   Remap reserved po...
72
  	Opt_mapposix, Opt_nomapposix,
8830d7e07   Sachin Prabhu   cifs: use standar...
73
74
75
76
77
  	Opt_mapchars, Opt_nomapchars, Opt_sfu,
  	Opt_nosfu, Opt_nodfs, Opt_posixpaths,
  	Opt_noposixpaths, Opt_nounix,
  	Opt_nocase,
  	Opt_brl, Opt_nobrl,
959326553   Steve French   CIFS: Add new mou...
78
  	Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
8830d7e07   Sachin Prabhu   cifs: use standar...
79
80
81
82
83
84
85
  	Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
  	Opt_nohard, Opt_nosoft,
  	Opt_nointr, Opt_intr,
  	Opt_nostrictsync, Opt_strictsync,
  	Opt_serverino, Opt_noserverino,
  	Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
  	Opt_acl, Opt_noacl, Opt_locallease,
1b3592049   Jeff Layton   cifs: remove supp...
86
  	Opt_sign, Opt_seal, Opt_noac,
8830d7e07   Sachin Prabhu   cifs: use standar...
87
  	Opt_fsc, Opt_mfsymlinks,
a0b3df5cf   Jeff Layton   cifs: add a "nosh...
88
  	Opt_multiuser, Opt_sloppy, Opt_nosharesock,
b2a307741   Steve French   [SMB3] Add parsin...
89
  	Opt_persistent, Opt_nopersistent,
592fafe64   Steve French   Add resilienthand...
90
  	Opt_resilient, Opt_noresilient,
8830d7e07   Sachin Prabhu   cifs: use standar...
91
92
93
94
95
96
  
  	/* Mount options which take numeric value */
  	Opt_backupuid, Opt_backupgid, Opt_uid,
  	Opt_cruid, Opt_gid, Opt_file_mode,
  	Opt_dirmode, Opt_port,
  	Opt_rsize, Opt_wsize, Opt_actimeo,
141891f47   Steve French   SMB3: Add mount p...
97
  	Opt_echo_interval, Opt_max_credits,
8830d7e07   Sachin Prabhu   cifs: use standar...
98
99
100
  
  	/* Mount options which take string value */
  	Opt_user, Opt_pass, Opt_ip,
73a999fab   Jeff Layton   cifs: ignore the ...
101
  	Opt_domain, Opt_srcaddr, Opt_iocharset,
8830d7e07   Sachin Prabhu   cifs: use standar...
102
  	Opt_netbiosname, Opt_servern,
23db65f51   Jeff Layton   cifs: add a smb_v...
103
  	Opt_ver, Opt_vers, Opt_sec, Opt_cache,
8830d7e07   Sachin Prabhu   cifs: use standar...
104
105
106
107
108
109
  
  	/* Mount options to be ignored */
  	Opt_ignore,
  
  	/* Options which could be blank */
  	Opt_blank_pass,
4fe9e9639   Sachin Prabhu   Cleanup handling ...
110
111
  	Opt_blank_user,
  	Opt_blank_ip,
8830d7e07   Sachin Prabhu   cifs: use standar...
112
113
114
115
116
117
118
119
120
121
  
  	Opt_err
  };
  
  static const match_table_t cifs_mount_option_tokens = {
  
  	{ Opt_user_xattr, "user_xattr" },
  	{ Opt_nouser_xattr, "nouser_xattr" },
  	{ Opt_forceuid, "forceuid" },
  	{ Opt_noforceuid, "noforceuid" },
72bd481f8   Jeff Layton   cifs: reinstate t...
122
123
  	{ Opt_forcegid, "forcegid" },
  	{ Opt_noforcegid, "noforcegid" },
8830d7e07   Sachin Prabhu   cifs: use standar...
124
125
126
127
128
129
  	{ Opt_noblocksend, "noblocksend" },
  	{ Opt_noautotune, "noautotune" },
  	{ Opt_hard, "hard" },
  	{ Opt_soft, "soft" },
  	{ Opt_perm, "perm" },
  	{ Opt_noperm, "noperm" },
2baa26825   Steve French   Remap reserved po...
130
  	{ Opt_mapchars, "mapchars" }, /* SFU style */
8830d7e07   Sachin Prabhu   cifs: use standar...
131
  	{ Opt_nomapchars, "nomapchars" },
2baa26825   Steve French   Remap reserved po...
132
133
  	{ Opt_mapposix, "mapposix" }, /* SFM style */
  	{ Opt_nomapposix, "nomapposix" },
8830d7e07   Sachin Prabhu   cifs: use standar...
134
135
136
137
138
139
140
141
142
143
144
145
146
  	{ Opt_sfu, "sfu" },
  	{ Opt_nosfu, "nosfu" },
  	{ Opt_nodfs, "nodfs" },
  	{ Opt_posixpaths, "posixpaths" },
  	{ Opt_noposixpaths, "noposixpaths" },
  	{ Opt_nounix, "nounix" },
  	{ Opt_nounix, "nolinux" },
  	{ Opt_nocase, "nocase" },
  	{ Opt_nocase, "ignorecase" },
  	{ Opt_brl, "brl" },
  	{ Opt_nobrl, "nobrl" },
  	{ Opt_nobrl, "nolock" },
  	{ Opt_forcemandatorylock, "forcemandatorylock" },
5cfdddcfc   Pavel Shilovsky   CIFS: Add missed ...
147
  	{ Opt_forcemandatorylock, "forcemand" },
8830d7e07   Sachin Prabhu   cifs: use standar...
148
149
  	{ Opt_setuids, "setuids" },
  	{ Opt_nosetuids, "nosetuids" },
959326553   Steve French   CIFS: Add new mou...
150
  	{ Opt_setuidfromacl, "idsfromsid" },
8830d7e07   Sachin Prabhu   cifs: use standar...
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
  	{ Opt_dynperm, "dynperm" },
  	{ Opt_nodynperm, "nodynperm" },
  	{ Opt_nohard, "nohard" },
  	{ Opt_nosoft, "nosoft" },
  	{ Opt_nointr, "nointr" },
  	{ Opt_intr, "intr" },
  	{ Opt_nostrictsync, "nostrictsync" },
  	{ Opt_strictsync, "strictsync" },
  	{ Opt_serverino, "serverino" },
  	{ Opt_noserverino, "noserverino" },
  	{ Opt_rwpidforward, "rwpidforward" },
  	{ Opt_cifsacl, "cifsacl" },
  	{ Opt_nocifsacl, "nocifsacl" },
  	{ Opt_acl, "acl" },
  	{ Opt_noacl, "noacl" },
  	{ Opt_locallease, "locallease" },
  	{ Opt_sign, "sign" },
  	{ Opt_seal, "seal" },
8830d7e07   Sachin Prabhu   cifs: use standar...
169
170
171
172
  	{ Opt_noac, "noac" },
  	{ Opt_fsc, "fsc" },
  	{ Opt_mfsymlinks, "mfsymlinks" },
  	{ Opt_multiuser, "multiuser" },
d81625587   Jeff Layton   cifs: handle "slo...
173
  	{ Opt_sloppy, "sloppy" },
a0b3df5cf   Jeff Layton   cifs: add a "nosh...
174
  	{ Opt_nosharesock, "nosharesock" },
b2a307741   Steve French   [SMB3] Add parsin...
175
176
  	{ Opt_persistent, "persistenthandles"},
  	{ Opt_nopersistent, "nopersistenthandles"},
592fafe64   Steve French   Add resilienthand...
177
178
  	{ Opt_resilient, "resilienthandles"},
  	{ Opt_noresilient, "noresilienthandles"},
8830d7e07   Sachin Prabhu   cifs: use standar...
179
180
181
182
183
184
185
186
187
188
189
190
191
  
  	{ Opt_backupuid, "backupuid=%s" },
  	{ Opt_backupgid, "backupgid=%s" },
  	{ Opt_uid, "uid=%s" },
  	{ Opt_cruid, "cruid=%s" },
  	{ Opt_gid, "gid=%s" },
  	{ Opt_file_mode, "file_mode=%s" },
  	{ Opt_dirmode, "dirmode=%s" },
  	{ Opt_dirmode, "dir_mode=%s" },
  	{ Opt_port, "port=%s" },
  	{ Opt_rsize, "rsize=%s" },
  	{ Opt_wsize, "wsize=%s" },
  	{ Opt_actimeo, "actimeo=%s" },
adfeb3e00   Steve French   cifs: Make echo i...
192
  	{ Opt_echo_interval, "echo_interval=%s" },
141891f47   Steve French   SMB3: Add mount p...
193
  	{ Opt_max_credits, "max_credits=%s" },
8830d7e07   Sachin Prabhu   cifs: use standar...
194

4fe9e9639   Sachin Prabhu   Cleanup handling ...
195
196
  	{ Opt_blank_user, "user=" },
  	{ Opt_blank_user, "username=" },
8830d7e07   Sachin Prabhu   cifs: use standar...
197
198
199
  	{ Opt_user, "user=%s" },
  	{ Opt_user, "username=%s" },
  	{ Opt_blank_pass, "pass=" },
3c15b4cf5   Jesper Nilsson   cifs: Add handlin...
200
  	{ Opt_blank_pass, "password=" },
8830d7e07   Sachin Prabhu   cifs: use standar...
201
202
  	{ Opt_pass, "pass=%s" },
  	{ Opt_pass, "password=%s" },
4fe9e9639   Sachin Prabhu   Cleanup handling ...
203
204
  	{ Opt_blank_ip, "ip=" },
  	{ Opt_blank_ip, "addr=" },
8830d7e07   Sachin Prabhu   cifs: use standar...
205
206
  	{ Opt_ip, "ip=%s" },
  	{ Opt_ip, "addr=%s" },
73a999fab   Jeff Layton   cifs: ignore the ...
207
208
209
  	{ Opt_ignore, "unc=%s" },
  	{ Opt_ignore, "target=%s" },
  	{ Opt_ignore, "path=%s" },
8830d7e07   Sachin Prabhu   cifs: use standar...
210
211
212
213
  	{ Opt_domain, "dom=%s" },
  	{ Opt_domain, "domain=%s" },
  	{ Opt_domain, "workgroup=%s" },
  	{ Opt_srcaddr, "srcaddr=%s" },
73a999fab   Jeff Layton   cifs: ignore the ...
214
  	{ Opt_ignore, "prefixpath=%s" },
8830d7e07   Sachin Prabhu   cifs: use standar...
215
  	{ Opt_iocharset, "iocharset=%s" },
8830d7e07   Sachin Prabhu   cifs: use standar...
216
217
218
  	{ Opt_netbiosname, "netbiosname=%s" },
  	{ Opt_servern, "servern=%s" },
  	{ Opt_ver, "ver=%s" },
23db65f51   Jeff Layton   cifs: add a smb_v...
219
  	{ Opt_vers, "vers=%s" },
8830d7e07   Sachin Prabhu   cifs: use standar...
220
  	{ Opt_sec, "sec=%s" },
15b6a4732   Jeff Layton   cifs: add a cache...
221
  	{ Opt_cache, "cache=%s" },
8830d7e07   Sachin Prabhu   cifs: use standar...
222
223
224
  
  	{ Opt_ignore, "cred" },
  	{ Opt_ignore, "credentials" },
a557b9761   Jeff Layton   cifs: make sure w...
225
226
  	{ Opt_ignore, "cred=%s" },
  	{ Opt_ignore, "credentials=%s" },
8830d7e07   Sachin Prabhu   cifs: use standar...
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
  	{ Opt_ignore, "guest" },
  	{ Opt_ignore, "rw" },
  	{ Opt_ignore, "ro" },
  	{ Opt_ignore, "suid" },
  	{ Opt_ignore, "nosuid" },
  	{ Opt_ignore, "exec" },
  	{ Opt_ignore, "noexec" },
  	{ Opt_ignore, "nodev" },
  	{ Opt_ignore, "noauto" },
  	{ Opt_ignore, "dev" },
  	{ Opt_ignore, "mand" },
  	{ Opt_ignore, "nomand" },
  	{ Opt_ignore, "_netdev" },
  
  	{ Opt_err, NULL }
  };
  
  enum {
  	Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
  	Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
7659624ff   Jeff Layton   cifs: reinstate s...
247
248
  	Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
  	Opt_sec_ntlmv2i, Opt_sec_lanman,
8830d7e07   Sachin Prabhu   cifs: use standar...
249
250
251
252
253
254
255
256
257
258
259
260
261
  	Opt_sec_none,
  
  	Opt_sec_err
  };
  
  static const match_table_t cifs_secflavor_tokens = {
  	{ Opt_sec_krb5, "krb5" },
  	{ Opt_sec_krb5i, "krb5i" },
  	{ Opt_sec_krb5p, "krb5p" },
  	{ Opt_sec_ntlmsspi, "ntlmsspi" },
  	{ Opt_sec_ntlmssp, "ntlmssp" },
  	{ Opt_ntlm, "ntlm" },
  	{ Opt_sec_ntlmi, "ntlmi" },
7659624ff   Jeff Layton   cifs: reinstate s...
262
263
  	{ Opt_sec_ntlmv2, "nontlm" },
  	{ Opt_sec_ntlmv2, "ntlmv2" },
8830d7e07   Sachin Prabhu   cifs: use standar...
264
  	{ Opt_sec_ntlmv2i, "ntlmv2i" },
8830d7e07   Sachin Prabhu   cifs: use standar...
265
266
267
268
269
  	{ Opt_sec_lanman, "lanman" },
  	{ Opt_sec_none, "none" },
  
  	{ Opt_sec_err, NULL }
  };
15b6a4732   Jeff Layton   cifs: add a cache...
270
271
272
273
274
275
276
277
278
279
280
281
282
283
  /* cache flavors */
  enum {
  	Opt_cache_loose,
  	Opt_cache_strict,
  	Opt_cache_none,
  	Opt_cache_err
  };
  
  static const match_table_t cifs_cacheflavor_tokens = {
  	{ Opt_cache_loose, "loose" },
  	{ Opt_cache_strict, "strict" },
  	{ Opt_cache_none, "none" },
  	{ Opt_cache_err, NULL }
  };
23db65f51   Jeff Layton   cifs: add a smb_v...
284
285
  static const match_table_t cifs_smb_version_tokens = {
  	{ Smb_1, SMB1_VERSION_STRING },
dd446b16e   Steve French   Add SMB2.02 diale...
286
  	{ Smb_20, SMB20_VERSION_STRING},
1080ef758   Steve French   CIFS: Introduce S...
287
  	{ Smb_21, SMB21_VERSION_STRING },
e4aa25e78   Steve French   [CIFS] Fix SMB2 n...
288
  	{ Smb_30, SMB30_VERSION_STRING },
20b6d8b42   Steve French   Add SMB3.02 diale...
289
  	{ Smb_302, SMB302_VERSION_STRING },
5f7fbf733   Steve French   Allow parsing ver...
290
291
  #ifdef CONFIG_CIFS_SMB311
  	{ Smb_311, SMB311_VERSION_STRING },
aab1893d5   Steve French   Add SMB3.11 mount...
292
  	{ Smb_311, ALT_SMB311_VERSION_STRING },
5f7fbf733   Steve French   Allow parsing ver...
293
294
  #endif /* SMB311 */
  	{ Smb_version_err, NULL }
23db65f51   Jeff Layton   cifs: add a smb_v...
295
  };
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
296
297
  static int ip_connect(struct TCP_Server_Info *server);
  static int generic_ip_connect(struct TCP_Server_Info *server);
b647c35f7   Jeff Layton   cifs: convert tli...
298
  static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
2de970ff6   Jeff Layton   cifs: implement r...
299
  static void cifs_prune_tlinks(struct work_struct *work);
b9bce2e9f   Jeff Layton   cifs: fix expand_...
300
301
  static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
  					const char *devname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302

d5c5605c2   Jeff Layton   cifs: make ipv6_c...
303
304
305
306
307
308
309
310
  /*
   * cifs tcp session reconnection
   *
   * mark tcp session as reconnecting so temporarily locked
   * mark all smb sessions as reconnecting for tcp session
   * reconnect tcp session
   * wake up waiters on reconnection? - (not needed currently)
   */
28ea5290d   Pavel Shilovsky   CIFS: Add SMB2 cr...
311
  int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
313
314
  cifs_reconnect(struct TCP_Server_Info *server)
  {
  	int rc = 0;
f1987b44f   Jeff Layton   cifs: reinstate s...
315
  	struct list_head *tmp, *tmp2;
96daf2b09   Steve French   [CIFS] Rename thr...
316
317
  	struct cifs_ses *ses;
  	struct cifs_tcon *tcon;
fb8c4b14d   Steve French   [CIFS] whitespace...
318
  	struct mid_q_entry *mid_entry;
3c1105df6   Jeff Layton   cifs: don't call ...
319
  	struct list_head retry_list;
50c2f7538   Steve French   [CIFS] whitespace...
320

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
  	spin_lock(&GlobalMid_Lock);
469ee614a   Jeff Layton   [CIFS] eliminate ...
322
  	if (server->tcpStatus == CifsExiting) {
fb8c4b14d   Steve French   [CIFS] whitespace...
323
  		/* the demux thread will exit normally
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
325
326
327
328
329
330
  		next time through the loop */
  		spin_unlock(&GlobalMid_Lock);
  		return rc;
  	} else
  		server->tcpStatus = CifsNeedReconnect;
  	spin_unlock(&GlobalMid_Lock);
  	server->maxBuf = 0;
aa24d1e96   Pavel Shilovsky   CIFS: Process rec...
331
332
333
  #ifdef CONFIG_CIFS_SMB2
  	server->max_read = 0;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334

f96637be0   Joe Perches   [CIFS] cifs: Rena...
335
336
  	cifs_dbg(FYI, "Reconnecting tcp session
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
338
339
  
  	/* before reconnecting the tcp session, mark the smb session (uid)
  		and the tid bad so they are not used until reconnected */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
340
341
342
  	cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect
  ",
  		 __func__);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
343
  	spin_lock(&cifs_tcp_ses_lock);
14fbf50d6   Jeff Layton   cifs: reinstate s...
344
  	list_for_each(tmp, &server->smb_ses_list) {
96daf2b09   Steve French   [CIFS] Rename thr...
345
  		ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
14fbf50d6   Jeff Layton   cifs: reinstate s...
346
347
  		ses->need_reconnect = true;
  		ses->ipc_tid = 0;
f1987b44f   Jeff Layton   cifs: reinstate s...
348
  		list_for_each(tmp2, &ses->tcon_list) {
96daf2b09   Steve French   [CIFS] Rename thr...
349
  			tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
3b7952109   Steve French   [CIFS] Fix cifs r...
350
  			tcon->need_reconnect = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
  	}
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
353
  	spin_unlock(&cifs_tcp_ses_lock);
2b84a36c5   Jeff Layton   cifs: allow for d...
354

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
355
  	/* do not want to be sending data on a socket we are freeing */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
356
357
  	cifs_dbg(FYI, "%s: tearing down socket
  ", __func__);
72ca545b2   Jeff Layton   cifs: convert tcp...
358
  	mutex_lock(&server->srv_mutex);
fb8c4b14d   Steve French   [CIFS] whitespace...
359
  	if (server->ssocket) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
360
361
362
  		cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx
  ",
  			 server->ssocket->state, server->ssocket->flags);
91cf45f02   Trond Myklebust   [NET]: Add the he...
363
  		kernel_sock_shutdown(server->ssocket, SHUT_WR);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
364
365
366
  		cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx
  ",
  			 server->ssocket->state, server->ssocket->flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
368
369
  		sock_release(server->ssocket);
  		server->ssocket = NULL;
  	}
5d0d28824   Shirish Pargaonkar   NTLM authenticati...
370
371
  	server->sequence_number = 0;
  	server->session_estab = false;
21e733930   Shirish Pargaonkar   NTLM auth and sig...
372
373
374
  	kfree(server->session_key.response);
  	server->session_key.response = NULL;
  	server->session_key.len = 0;
fda359436   Steve French   [CIFS] cifs: reco...
375
  	server->lstrp = jiffies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376

2b84a36c5   Jeff Layton   cifs: allow for d...
377
  	/* mark submitted MIDs for retry and issue callback */
3c1105df6   Jeff Layton   cifs: don't call ...
378
  	INIT_LIST_HEAD(&retry_list);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
379
380
  	cifs_dbg(FYI, "%s: moving mids to private list
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
  	spin_lock(&GlobalMid_Lock);
2b84a36c5   Jeff Layton   cifs: allow for d...
382
383
  	list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
  		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
7c9421e1a   Pavel Shilovsky   CIFS: Change mid_...
384
385
  		if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
  			mid_entry->mid_state = MID_RETRY_NEEDED;
3c1105df6   Jeff Layton   cifs: don't call ...
386
387
388
  		list_move(&mid_entry->qhead, &retry_list);
  	}
  	spin_unlock(&GlobalMid_Lock);
820962dc7   Rabin Vincent   cifs: fix race be...
389
  	mutex_unlock(&server->srv_mutex);
3c1105df6   Jeff Layton   cifs: don't call ...
390

f96637be0   Joe Perches   [CIFS] cifs: Rena...
391
392
  	cifs_dbg(FYI, "%s: issuing mid callbacks
  ", __func__);
3c1105df6   Jeff Layton   cifs: don't call ...
393
394
  	list_for_each_safe(tmp, tmp2, &retry_list) {
  		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
2b84a36c5   Jeff Layton   cifs: allow for d...
395
396
  		list_del_init(&mid_entry->qhead);
  		mid_entry->callback(mid_entry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398

7fdbaa1b8   Jeff Layton   cifs: don't allow...
399
  	do {
6c3d8909d   Steve French   [CIFS] Allow cifs...
400
  		try_to_freeze();
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
401
402
  
  		/* we should try only the port we connected to before */
73e216a8a   Jeff Layton   cifs: ensure that...
403
  		mutex_lock(&server->srv_mutex);
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
404
  		rc = generic_ip_connect(server);
fb8c4b14d   Steve French   [CIFS] whitespace...
405
  		if (rc) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
406
407
  			cifs_dbg(FYI, "reconnect error %d
  ", rc);
4afe260ba   Federico Sauter   CIFS: Fix race co...
408
  			mutex_unlock(&server->srv_mutex);
0cb766ae6   Steve French   [PATCH] cifs: Do ...
409
  			msleep(3000);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
411
412
  		} else {
  			atomic_inc(&tcpSesReconnectCount);
  			spin_lock(&GlobalMid_Lock);
469ee614a   Jeff Layton   [CIFS] eliminate ...
413
  			if (server->tcpStatus != CifsExiting)
fd88ce931   Steve French   [CIFS] cifs: clar...
414
  				server->tcpStatus = CifsNeedNegotiate;
fb8c4b14d   Steve French   [CIFS] whitespace...
415
  			spin_unlock(&GlobalMid_Lock);
4afe260ba   Federico Sauter   CIFS: Fix race co...
416
  			mutex_unlock(&server->srv_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
  		}
7fdbaa1b8   Jeff Layton   cifs: don't allow...
418
  	} while (server->tcpStatus == CifsNeedReconnect);
2b84a36c5   Jeff Layton   cifs: allow for d...
419

b8c600120   Sachin Prabhu   Call echo service...
420
421
  	if (server->tcpStatus == CifsNeedNegotiate)
  		mod_delayed_work(cifsiod_wq, &server->echo, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
423
  	return rc;
  }
c74093b69   Jeff Layton   cifs: set up recu...
424
425
426
427
428
429
  static void
  cifs_echo_request(struct work_struct *work)
  {
  	int rc;
  	struct TCP_Server_Info *server = container_of(work,
  					struct TCP_Server_Info, echo.work);
b8c600120   Sachin Prabhu   Call echo service...
430
431
432
433
434
435
436
437
438
439
  	unsigned long echo_interval;
  
  	/*
  	 * If we need to renegotiate, set echo interval to zero to
  	 * immediately call echo service where we can renegotiate.
  	 */
  	if (server->tcpStatus == CifsNeedNegotiate)
  		echo_interval = 0;
  	else
  		echo_interval = server->echo_interval;
c74093b69   Jeff Layton   cifs: set up recu...
440

247ec9b41   Jeff Layton   cifs: don't send ...
441
  	/*
b8c600120   Sachin Prabhu   Call echo service...
442
443
  	 * We cannot send an echo if it is disabled.
  	 * Also, no need to ping if we got a response recently.
247ec9b41   Jeff Layton   cifs: don't send ...
444
  	 */
4fcd1813e   Steve French   Fix reconnect to ...
445
446
  
  	if (server->tcpStatus == CifsNeedReconnect ||
b8c600120   Sachin Prabhu   Call echo service...
447
448
  	    server->tcpStatus == CifsExiting ||
  	    server->tcpStatus == CifsNew ||
f6d761786   Pavel Shilovsky   CIFS: Move echo c...
449
  	    (server->ops->can_echo && !server->ops->can_echo(server)) ||
adfeb3e00   Steve French   cifs: Make echo i...
450
  	    time_before(jiffies, server->lstrp + echo_interval - HZ))
c74093b69   Jeff Layton   cifs: set up recu...
451
  		goto requeue_echo;
f6d761786   Pavel Shilovsky   CIFS: Move echo c...
452
  	rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
c74093b69   Jeff Layton   cifs: set up recu...
453
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
454
455
456
  		cifs_dbg(FYI, "Unable to send echo request to server: %s
  ",
  			 server->hostname);
c74093b69   Jeff Layton   cifs: set up recu...
457
458
  
  requeue_echo:
b8c600120   Sachin Prabhu   Call echo service...
459
  	queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
c74093b69   Jeff Layton   cifs: set up recu...
460
  }
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
461
  static bool
2a37ef94b   Jeff Layton   cifs: move buffer...
462
  allocate_buffers(struct TCP_Server_Info *server)
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
463
  {
2a37ef94b   Jeff Layton   cifs: move buffer...
464
465
466
  	if (!server->bigbuf) {
  		server->bigbuf = (char *)cifs_buf_get();
  		if (!server->bigbuf) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
467
468
  			cifs_dbg(VFS, "No memory for large SMB response
  ");
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
469
470
471
472
  			msleep(3000);
  			/* retry will check if exiting */
  			return false;
  		}
2a37ef94b   Jeff Layton   cifs: move buffer...
473
  	} else if (server->large_buf) {
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
474
  		/* we are reusing a dirty large buf, clear its start */
1887f6010   Pavel Shilovsky   CIFS: Move header...
475
  		memset(server->bigbuf, 0, HEADER_SIZE(server));
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
476
  	}
2a37ef94b   Jeff Layton   cifs: move buffer...
477
478
479
  	if (!server->smallbuf) {
  		server->smallbuf = (char *)cifs_small_buf_get();
  		if (!server->smallbuf) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
480
481
  			cifs_dbg(VFS, "No memory for SMB response
  ");
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
482
483
484
485
486
487
488
  			msleep(1000);
  			/* retry will check if exiting */
  			return false;
  		}
  		/* beginning of smb buffer is cleared in our buf_get */
  	} else {
  		/* if existing small buf clear beginning */
1887f6010   Pavel Shilovsky   CIFS: Move header...
489
  		memset(server->smallbuf, 0, HEADER_SIZE(server));
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
490
  	}
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
491
492
  	return true;
  }
ba749e6d5   Jeff Layton   cifs: check for u...
493
494
495
  static bool
  server_unresponsive(struct TCP_Server_Info *server)
  {
6dae51a58   Pavel Shilovsky   CIFS: Delete echo...
496
497
498
499
500
501
502
503
504
505
506
507
  	/*
  	 * We need to wait 2 echo intervals to make sure we handle such
  	 * situations right:
  	 * 1s  client sends a normal SMB request
  	 * 2s  client gets a response
  	 * 30s echo workqueue job pops, and decides we got a response recently
  	 *     and don't need to send another
  	 * ...
  	 * 65s kernel_recvmsg times out, and we see that we haven't gotten
  	 *     a response in >60s.
  	 */
  	if (server->tcpStatus == CifsGood &&
adfeb3e00   Steve French   cifs: Make echo i...
508
509
510
511
  	    time_after(jiffies, server->lstrp + 2 * server->echo_interval)) {
  		cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...
  ",
  			 server->hostname, (2 * server->echo_interval) / HZ);
ba749e6d5   Jeff Layton   cifs: check for u...
512
513
514
515
516
517
518
  		cifs_reconnect(server);
  		wake_up(&server->response_q);
  		return true;
  	}
  
  	return false;
  }
71335664c   Al Viro   cifs: don't bothe...
519
520
  static int
  cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
521
  {
a52c1eb7a   Jeff Layton   cifs: simplify re...
522
523
  	int length = 0;
  	int total_read;
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
524

71335664c   Al Viro   cifs: don't bothe...
525
526
  	smb_msg->msg_control = NULL;
  	smb_msg->msg_controllen = 0;
e831e6cf3   Jeff Layton   cifs: make smb_ms...
527

71335664c   Al Viro   cifs: don't bothe...
528
  	for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
95edcff49   Jeff Layton   cifs: attempt to ...
529
  		try_to_freeze();
71335664c   Al Viro   cifs: don't bothe...
530
531
  		if (server_unresponsive(server))
  			return -ECONNABORTED;
ba749e6d5   Jeff Layton   cifs: check for u...
532

71335664c   Al Viro   cifs: don't bothe...
533
  		length = sock_recvmsg(server->ssocket, smb_msg, 0);
42c4dfc21   Jeff Layton   cifs: turn read_f...
534

71335664c   Al Viro   cifs: don't bothe...
535
536
  		if (server->tcpStatus == CifsExiting)
  			return -ESHUTDOWN;
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
537

71335664c   Al Viro   cifs: don't bothe...
538
  		if (server->tcpStatus == CifsNeedReconnect) {
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
539
  			cifs_reconnect(server);
71335664c   Al Viro   cifs: don't bothe...
540
541
542
543
544
545
  			return -ECONNABORTED;
  		}
  
  		if (length == -ERESTARTSYS ||
  		    length == -EAGAIN ||
  		    length == -EINTR) {
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
546
547
548
549
550
551
552
  			/*
  			 * Minimum sleep to prevent looping, allowing socket
  			 * to clear and app threads to set tcpStatus
  			 * CifsNeedReconnect if server hung.
  			 */
  			usleep_range(1000, 2000);
  			length = 0;
a52c1eb7a   Jeff Layton   cifs: simplify re...
553
  			continue;
71335664c   Al Viro   cifs: don't bothe...
554
555
556
  		}
  
  		if (length <= 0) {
09aab880f   Al Viro   cifs: no need to ...
557
558
  			cifs_dbg(FYI, "Received no data or error: %d
  ", length);
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
559
  			cifs_reconnect(server);
71335664c   Al Viro   cifs: don't bothe...
560
  			return -ECONNABORTED;
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
561
562
  		}
  	}
a52c1eb7a   Jeff Layton   cifs: simplify re...
563
  	return total_read;
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
564
  }
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
565

e28bc5b1f   Jeff Layton   cifs: add cifs_as...
566
567
568
  int
  cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
  		      unsigned int to_read)
42c4dfc21   Jeff Layton   cifs: turn read_f...
569
  {
71335664c   Al Viro   cifs: don't bothe...
570
571
572
  	struct msghdr smb_msg;
  	struct kvec iov = {.iov_base = buf, .iov_len = to_read};
  	iov_iter_kvec(&smb_msg.msg_iter, READ | ITER_KVEC, &iov, 1, to_read);
42c4dfc21   Jeff Layton   cifs: turn read_f...
573

71335664c   Al Viro   cifs: don't bothe...
574
575
  	return cifs_readv_from_socket(server, &smb_msg);
  }
42c4dfc21   Jeff Layton   cifs: turn read_f...
576

71335664c   Al Viro   cifs: don't bothe...
577
578
579
580
581
582
583
584
  int
  cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
  		      unsigned int to_read)
  {
  	struct msghdr smb_msg;
  	struct bio_vec bv = {.bv_page = page, .bv_len = to_read};
  	iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read);
  	return cifs_readv_from_socket(server, &smb_msg);
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
585
  }
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
586
  static bool
fe11e4ccb   Jeff Layton   cifs: clean up ch...
587
  is_smb_response(struct TCP_Server_Info *server, unsigned char type)
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
588
  {
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
589
590
591
592
593
  	/*
  	 * The first byte big endian of the length field,
  	 * is actually not part of the length but the type
  	 * with the most common, zero, as regular data.
  	 */
fe11e4ccb   Jeff Layton   cifs: clean up ch...
594
595
596
597
598
  	switch (type) {
  	case RFC1002_SESSION_MESSAGE:
  		/* Regular SMB response */
  		return true;
  	case RFC1002_SESSION_KEEP_ALIVE:
f96637be0   Joe Perches   [CIFS] cifs: Rena...
599
600
  		cifs_dbg(FYI, "RFC 1002 session keep alive
  ");
fe11e4ccb   Jeff Layton   cifs: clean up ch...
601
602
  		break;
  	case RFC1002_POSITIVE_SESSION_RESPONSE:
f96637be0   Joe Perches   [CIFS] cifs: Rena...
603
604
  		cifs_dbg(FYI, "RFC 1002 positive session response
  ");
fe11e4ccb   Jeff Layton   cifs: clean up ch...
605
606
  		break;
  	case RFC1002_NEGATIVE_SESSION_RESPONSE:
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
607
608
609
610
  		/*
  		 * We get this from Windows 98 instead of an error on
  		 * SMB negprot response.
  		 */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
611
612
  		cifs_dbg(FYI, "RFC 1002 negative session response
  ");
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
613
614
615
616
617
618
619
620
  		/* give server a second to clean up */
  		msleep(1000);
  		/*
  		 * Always try 445 first on reconnect since we get NACK
  		 * on some if we ever connected to port 139 (the NACK
  		 * is since we do not begin with RFC1001 session
  		 * initialize frame).
  		 */
fe11e4ccb   Jeff Layton   cifs: clean up ch...
621
  		cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
622
623
  		cifs_reconnect(server);
  		wake_up(&server->response_q);
fe11e4ccb   Jeff Layton   cifs: clean up ch...
624
625
  		break;
  	default:
f96637be0   Joe Perches   [CIFS] cifs: Rena...
626
627
  		cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x
  ", type);
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
628
  		cifs_reconnect(server);
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
629
  	}
fe11e4ccb   Jeff Layton   cifs: clean up ch...
630
  	return false;
98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
631
  }
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
632
633
  void
  dequeue_mid(struct mid_q_entry *mid, bool malformed)
ea1f4502f   Jeff Layton   cifs: move mid fi...
634
  {
ad69bae17   Pavel Shilovsky   CIFS: Move mid se...
635
  #ifdef CONFIG_CIFS_STATS2
ea1f4502f   Jeff Layton   cifs: move mid fi...
636
  	mid->when_received = jiffies;
ad69bae17   Pavel Shilovsky   CIFS: Move mid se...
637
  #endif
ea1f4502f   Jeff Layton   cifs: move mid fi...
638
639
  	spin_lock(&GlobalMid_Lock);
  	if (!malformed)
7c9421e1a   Pavel Shilovsky   CIFS: Change mid_...
640
  		mid->mid_state = MID_RESPONSE_RECEIVED;
ea1f4502f   Jeff Layton   cifs: move mid fi...
641
  	else
7c9421e1a   Pavel Shilovsky   CIFS: Change mid_...
642
  		mid->mid_state = MID_RESPONSE_MALFORMED;
ea1f4502f   Jeff Layton   cifs: move mid fi...
643
  	list_del_init(&mid->qhead);
ad69bae17   Pavel Shilovsky   CIFS: Move mid se...
644
  	spin_unlock(&GlobalMid_Lock);
ea1f4502f   Jeff Layton   cifs: move mid fi...
645
  }
ad69bae17   Pavel Shilovsky   CIFS: Move mid se...
646

c8054ebdb   Jeff Layton   cifs: find mid ea...
647
648
  static void
  handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
d4e4854fd   Pavel Shilovsky   CIFS: Separate pr...
649
  	   char *buf, int malformed)
ea1f4502f   Jeff Layton   cifs: move mid fi...
650
  {
316cf94a9   Pavel Shilovsky   CIFS: Move trans2...
651
652
  	if (server->ops->check_trans2 &&
  	    server->ops->check_trans2(mid, server, buf, malformed))
c8054ebdb   Jeff Layton   cifs: find mid ea...
653
  		return;
ea1f4502f   Jeff Layton   cifs: move mid fi...
654
  	mid->resp_buf = buf;
7c9421e1a   Pavel Shilovsky   CIFS: Change mid_...
655
  	mid->large_buf = server->large_buf;
2a37ef94b   Jeff Layton   cifs: move buffer...
656
657
658
659
660
661
662
663
  	/* Was previous buf put in mpx struct for multi-rsp? */
  	if (!mid->multiRsp) {
  		/* smb buffer will be freed by user thread */
  		if (server->large_buf)
  			server->bigbuf = NULL;
  		else
  			server->smallbuf = NULL;
  	}
ffc00e27a   Jeff Layton   cifs: eliminate i...
664
  	dequeue_mid(mid, malformed);
ad69bae17   Pavel Shilovsky   CIFS: Move mid se...
665
  }
762dfd105   Pavel Shilovsky   CIFS: Cleanup dem...
666
667
668
669
670
671
672
673
674
675
676
677
678
  static void clean_demultiplex_info(struct TCP_Server_Info *server)
  {
  	int length;
  
  	/* take it off the list, if it's not already */
  	spin_lock(&cifs_tcp_ses_lock);
  	list_del_init(&server->tcp_ses_list);
  	spin_unlock(&cifs_tcp_ses_lock);
  
  	spin_lock(&GlobalMid_Lock);
  	server->tcpStatus = CifsExiting;
  	spin_unlock(&GlobalMid_Lock);
  	wake_up_all(&server->response_q);
2d86dbc97   Pavel Shilovsky   CIFS: Introduce c...
679
  	/* check if we have blocked requests that need to free */
fc40f9cf8   Pavel Shilovsky   CIFS: Simplify in...
680
  	spin_lock(&server->req_lock);
2d86dbc97   Pavel Shilovsky   CIFS: Introduce c...
681
682
  	if (server->credits <= 0)
  		server->credits = 1;
fc40f9cf8   Pavel Shilovsky   CIFS: Simplify in...
683
  	spin_unlock(&server->req_lock);
762dfd105   Pavel Shilovsky   CIFS: Cleanup dem...
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
  	/*
  	 * Although there should not be any requests blocked on this queue it
  	 * can not hurt to be paranoid and try to wake up requests that may
  	 * haven been blocked when more than 50 at time were on the wire to the
  	 * same server - they now will see the session is in exit state and get
  	 * out of SendReceive.
  	 */
  	wake_up_all(&server->request_q);
  	/* give those requests time to exit */
  	msleep(125);
  
  	if (server->ssocket) {
  		sock_release(server->ssocket);
  		server->ssocket = NULL;
  	}
  
  	if (!list_empty(&server->pending_mid_q)) {
  		struct list_head dispose_list;
  		struct mid_q_entry *mid_entry;
  		struct list_head *tmp, *tmp2;
  
  		INIT_LIST_HEAD(&dispose_list);
  		spin_lock(&GlobalMid_Lock);
  		list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
  			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
709
710
  			cifs_dbg(FYI, "Clearing mid 0x%llx
  ", mid_entry->mid);
7c9421e1a   Pavel Shilovsky   CIFS: Change mid_...
711
  			mid_entry->mid_state = MID_SHUTDOWN;
762dfd105   Pavel Shilovsky   CIFS: Cleanup dem...
712
713
714
715
716
717
718
  			list_move(&mid_entry->qhead, &dispose_list);
  		}
  		spin_unlock(&GlobalMid_Lock);
  
  		/* now walk dispose list and issue callbacks */
  		list_for_each_safe(tmp, tmp2, &dispose_list) {
  			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
719
720
  			cifs_dbg(FYI, "Callback mid 0x%llx
  ", mid_entry->mid);
762dfd105   Pavel Shilovsky   CIFS: Cleanup dem...
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
  			list_del_init(&mid_entry->qhead);
  			mid_entry->callback(mid_entry);
  		}
  		/* 1/8th of sec is more than enough time for them to exit */
  		msleep(125);
  	}
  
  	if (!list_empty(&server->pending_mid_q)) {
  		/*
  		 * mpx threads have not exited yet give them at least the smb
  		 * send timeout time for long ops.
  		 *
  		 * Due to delays on oplock break requests, we need to wait at
  		 * least 45 seconds before giving up on a request getting a
  		 * response and going ahead and killing cifsd.
  		 */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
737
738
  		cifs_dbg(FYI, "Wait for exit from demultiplex thread
  ");
762dfd105   Pavel Shilovsky   CIFS: Cleanup dem...
739
740
741
742
743
744
745
746
747
748
749
750
  		msleep(46000);
  		/*
  		 * If threads still have not exited they are probably never
  		 * coming home not much else we can do but free the memory.
  		 */
  	}
  
  	kfree(server->hostname);
  	kfree(server);
  
  	length = atomic_dec_return(&tcpSesAllocCount);
  	if (length > 0)
11d833604   David Rientjes   mm, mempool: do n...
751
  		mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
762dfd105   Pavel Shilovsky   CIFS: Cleanup dem...
752
  }
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
753
  static int
e9097ab48   Jeff Layton   cifs: break out 3...
754
755
756
757
  standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
  {
  	int length;
  	char *buf = server->smallbuf;
d4e4854fd   Pavel Shilovsky   CIFS: Separate pr...
758
  	unsigned int pdu_length = get_rfc1002_length(buf);
e9097ab48   Jeff Layton   cifs: break out 3...
759
760
  
  	/* make sure this will fit in a large buffer */
1887f6010   Pavel Shilovsky   CIFS: Move header...
761
  	if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - 4) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
762
763
  		cifs_dbg(VFS, "SMB response too long (%u bytes)
  ", pdu_length);
e9097ab48   Jeff Layton   cifs: break out 3...
764
765
  		cifs_reconnect(server);
  		wake_up(&server->response_q);
3fabaa274   Pavel Shilovsky   CIFS: Indicate re...
766
  		return -ECONNABORTED;
e9097ab48   Jeff Layton   cifs: break out 3...
767
768
769
770
771
  	}
  
  	/* switch to large buffer if too big for a small one */
  	if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
  		server->large_buf = true;
d4e4854fd   Pavel Shilovsky   CIFS: Separate pr...
772
  		memcpy(server->bigbuf, buf, server->total_read);
e9097ab48   Jeff Layton   cifs: break out 3...
773
  		buf = server->bigbuf;
e9097ab48   Jeff Layton   cifs: break out 3...
774
775
776
  	}
  
  	/* now read the rest */
1887f6010   Pavel Shilovsky   CIFS: Move header...
777
778
  	length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
  				pdu_length - HEADER_SIZE(server) + 1 + 4);
e9097ab48   Jeff Layton   cifs: break out 3...
779
780
781
  	if (length < 0)
  		return length;
  	server->total_read += length;
d4e4854fd   Pavel Shilovsky   CIFS: Separate pr...
782
  	dump_smb(buf, server->total_read);
e9097ab48   Jeff Layton   cifs: break out 3...
783
784
785
786
787
788
789
790
791
792
  
  	/*
  	 * We know that we received enough to get to the MID as we
  	 * checked the pdu_length earlier. Now check to see
  	 * if the rest of the header is OK. We borrow the length
  	 * var for the rest of the loop to avoid a new stack var.
  	 *
  	 * 48 bytes is enough to display the header and a little bit
  	 * into the payload for debugging purposes.
  	 */
373512ec5   Steve French   Prepare for encry...
793
  	length = server->ops->check_message(buf, server->total_read, server);
e9097ab48   Jeff Layton   cifs: break out 3...
794
795
796
  	if (length != 0)
  		cifs_dump_mem("Bad SMB: ", buf,
  			min_t(unsigned int, server->total_read, 48));
2e44b2887   Pavel Shilovsky   CIFS: Process opl...
797
798
799
  	if (server->ops->is_status_pending &&
  	    server->ops->is_status_pending(buf, server, length))
  		return -1;
ff4fa4a25   Jeff Layton   cifs: don't retur...
800
801
  	if (!mid)
  		return length;
e9097ab48   Jeff Layton   cifs: break out 3...
802

d4e4854fd   Pavel Shilovsky   CIFS: Separate pr...
803
  	handle_mid(mid, server, buf, length);
ff4fa4a25   Jeff Layton   cifs: don't retur...
804
  	return 0;
e9097ab48   Jeff Layton   cifs: break out 3...
805
806
807
  }
  
  static int
7c97c200e   Al Viro   cifs: fix the typ...
808
  cifs_demultiplex_thread(void *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
809
810
  {
  	int length;
7c97c200e   Al Viro   cifs: fix the typ...
811
  	struct TCP_Server_Info *server = p;
2a37ef94b   Jeff Layton   cifs: move buffer...
812
813
  	unsigned int pdu_length;
  	char *buf = NULL;
a5c3e1c72   Steve French   Revert "cifs: No ...
814
  	struct task_struct *task_to_wake = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815
  	struct mid_q_entry *mid_entry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
816

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817
  	current->flags |= PF_MEMALLOC;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
818
819
  	cifs_dbg(FYI, "Demultiplex PID: %d
  ", task_pid_nr(current));
93d0ec851   Jeff Layton   remove locking ar...
820
821
822
  
  	length = atomic_inc_return(&tcpSesAllocCount);
  	if (length > 1)
11d833604   David Rientjes   mm, mempool: do n...
823
  		mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824

831441862   Rafael J. Wysocki   Freezer: make ker...
825
  	set_freezable();
469ee614a   Jeff Layton   [CIFS] eliminate ...
826
  	while (server->tcpStatus != CifsExiting) {
ede1327ea   Steve French   [PATCH] cifs: Add...
827
828
  		if (try_to_freeze())
  			continue;
b8643e1b5   Steve French   [PATCH] cifs: Do ...
829

2a37ef94b   Jeff Layton   cifs: move buffer...
830
  		if (!allocate_buffers(server))
3d9c2472a   Pavel Shilovsky   CIFS: Move buffer...
831
  			continue;
b8643e1b5   Steve French   [PATCH] cifs: Do ...
832

2a37ef94b   Jeff Layton   cifs: move buffer...
833
  		server->large_buf = false;
2a37ef94b   Jeff Layton   cifs: move buffer...
834
  		buf = server->smallbuf;
f01d5e14e   Steve French   [CIFS] fix for in...
835
  		pdu_length = 4; /* enough to get RFC1001 header */
fda359436   Steve French   [CIFS] cifs: reco...
836

e28bc5b1f   Jeff Layton   cifs: add cifs_as...
837
  		length = cifs_read_from_socket(server, buf, pdu_length);
a52c1eb7a   Jeff Layton   cifs: simplify re...
838
  		if (length < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839
  			continue;
2a37ef94b   Jeff Layton   cifs: move buffer...
840
  		server->total_read = length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
841

98bac62c9   Pavel Shilovsky   CIFS: Move RFC100...
842
843
844
845
  		/*
  		 * The right amount was read from socket - 4 bytes,
  		 * so we can now interpret the length field.
  		 */
d4e4854fd   Pavel Shilovsky   CIFS: Separate pr...
846
  		pdu_length = get_rfc1002_length(buf);
70ca734a1   Steve French   [CIFS] Various mi...
847

f96637be0   Joe Perches   [CIFS] cifs: Rena...
848
849
  		cifs_dbg(FYI, "RFC1002 header 0x%x
  ", pdu_length);
fe11e4ccb   Jeff Layton   cifs: clean up ch...
850
  		if (!is_smb_response(server, buf[0]))
fb8c4b14d   Steve French   [CIFS] whitespace...
851
  			continue;
e4eb295d3   Steve French   [PATCH] cifs: Han...
852

89482a56a   Jeff Layton   cifs: add a third...
853
  		/* make sure we have enough to get to the MID */
1887f6010   Pavel Shilovsky   CIFS: Move header...
854
  		if (pdu_length < HEADER_SIZE(server) - 1 - 4) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
855
856
857
  			cifs_dbg(VFS, "SMB response too short (%u bytes)
  ",
  				 pdu_length);
89482a56a   Jeff Layton   cifs: add a third...
858
859
860
  			cifs_reconnect(server);
  			wake_up(&server->response_q);
  			continue;
e4eb295d3   Steve French   [PATCH] cifs: Han...
861
  		}
e7015fb1c   Pavel Shilovsky   CIFS: Simplify so...
862

89482a56a   Jeff Layton   cifs: add a third...
863
  		/* read down to the MID */
e28bc5b1f   Jeff Layton   cifs: add cifs_as...
864
  		length = cifs_read_from_socket(server, buf + 4,
1887f6010   Pavel Shilovsky   CIFS: Move header...
865
  					       HEADER_SIZE(server) - 1 - 4);
89482a56a   Jeff Layton   cifs: add a third...
866
  		if (length < 0)
e4eb295d3   Steve French   [PATCH] cifs: Han...
867
  			continue;
2a37ef94b   Jeff Layton   cifs: move buffer...
868
  		server->total_read += length;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
869

8aa26f3ed   Pavel Shilovsky   CIFS: Move protoc...
870
  		mid_entry = server->ops->find_mid(server, buf);
50c2f7538   Steve French   [CIFS] whitespace...
871

44d22d846   Jeff Layton   cifs: add a callb...
872
873
874
875
  		if (!mid_entry || !mid_entry->receive)
  			length = standard_receive3(server, mid_entry);
  		else
  			length = mid_entry->receive(server, mid_entry);
71823baff   Jeff Layton   cifs: don't alway...
876

e9097ab48   Jeff Layton   cifs: break out 3...
877
  		if (length < 0)
fe11e4ccb   Jeff Layton   cifs: clean up ch...
878
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879

d4e4854fd   Pavel Shilovsky   CIFS: Separate pr...
880
  		if (server->large_buf)
2a37ef94b   Jeff Layton   cifs: move buffer...
881
  			buf = server->bigbuf;
fda359436   Steve French   [CIFS] cifs: reco...
882

fda359436   Steve French   [CIFS] cifs: reco...
883
  		server->lstrp = jiffies;
2b84a36c5   Jeff Layton   cifs: allow for d...
884
  		if (mid_entry != NULL) {
2a37ef94b   Jeff Layton   cifs: move buffer...
885
886
  			if (!mid_entry->multiRsp || mid_entry->multiEnd)
  				mid_entry->callback(mid_entry);
7f0adb53b   Pavel Shilovsky   CIFS: Make access...
887
888
  		} else if (!server->ops->is_oplock_break ||
  			   !server->ops->is_oplock_break(buf, server)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
889
890
891
  			cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d
  ",
  				 atomic_read(&midCount));
1887f6010   Pavel Shilovsky   CIFS: Move header...
892
893
  			cifs_dump_mem("Received Data is: ", buf,
  				      HEADER_SIZE(server));
3979877e5   Steve French   [CIFS] Support fo...
894
  #ifdef CONFIG_CIFS_DEBUG2
7f0adb53b   Pavel Shilovsky   CIFS: Make access...
895
896
  			if (server->ops->dump_detail)
  				server->ops->dump_detail(buf);
3979877e5   Steve French   [CIFS] Support fo...
897
898
  			cifs_dump_mids(server);
  #endif /* CIFS_DEBUG2 */
50c2f7538   Steve French   [CIFS] whitespace...
899

e4eb295d3   Steve French   [PATCH] cifs: Han...
900
901
  		}
  	} /* end while !EXITING */
fd62cb7e7   Justin P. Mattock   fs:cifs:connect.c...
902
  	/* buffer usually freed in free_mid - need to free it here on exit */
2a37ef94b   Jeff Layton   cifs: move buffer...
903
904
905
  	cifs_buf_release(server->bigbuf);
  	if (server->smallbuf) /* no sense logging a debug message if NULL */
  		cifs_small_buf_release(server->smallbuf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
906

a5c3e1c72   Steve French   Revert "cifs: No ...
907
  	task_to_wake = xchg(&server->tsk, NULL);
762dfd105   Pavel Shilovsky   CIFS: Cleanup dem...
908
  	clean_demultiplex_info(server);
a5c3e1c72   Steve French   Revert "cifs: No ...
909
910
911
912
913
914
915
916
917
918
  
  	/* if server->tsk was NULL then wait for a signal before exiting */
  	if (!task_to_wake) {
  		set_current_state(TASK_INTERRUPTIBLE);
  		while (!signal_pending(current)) {
  			schedule();
  			set_current_state(TASK_INTERRUPTIBLE);
  		}
  		set_current_state(TASK_RUNNING);
  	}
0468a2cf9   Jeff Layton   cifs: take module...
919
  	module_put_and_exit(0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
920
  }
c359cf3c6   Jeff Layton   [CIFS] add hostna...
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
  /* extract the host portion of the UNC string */
  static char *
  extract_hostname(const char *unc)
  {
  	const char *src;
  	char *dst, *delim;
  	unsigned int len;
  
  	/* skip double chars at beginning of string */
  	/* BB: check validity of these bytes? */
  	src = unc + 2;
  
  	/* delimiter between hostname and sharename is always '\\' now */
  	delim = strchr(src, '\\');
  	if (!delim)
  		return ERR_PTR(-EINVAL);
  
  	len = delim - src;
  	dst = kmalloc((len + 1), GFP_KERNEL);
  	if (dst == NULL)
  		return ERR_PTR(-ENOMEM);
  
  	memcpy(dst, src, len);
  	dst[len] = '\0';
  
  	return dst;
  }
8830d7e07   Sachin Prabhu   cifs: use standar...
948
949
950
951
952
953
954
955
  static int get_option_ul(substring_t args[], unsigned long *option)
  {
  	int rc;
  	char *string;
  
  	string = match_strdup(args);
  	if (string == NULL)
  		return -ENOMEM;
bfa890a3c   Sachin Prabhu   Fix number parsin...
956
  	rc = kstrtoul(string, 0, option);
8830d7e07   Sachin Prabhu   cifs: use standar...
957
958
959
960
  	kfree(string);
  
  	return rc;
  }
3da465650   Eric W. Biederman   cifs: Modify stru...
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
  static int get_option_uid(substring_t args[], kuid_t *result)
  {
  	unsigned long value;
  	kuid_t uid;
  	int rc;
  
  	rc = get_option_ul(args, &value);
  	if (rc)
  		return rc;
  
  	uid = make_kuid(current_user_ns(), value);
  	if (!uid_valid(uid))
  		return -EINVAL;
  
  	*result = uid;
  	return 0;
  }
  
  static int get_option_gid(substring_t args[], kgid_t *result)
  {
  	unsigned long value;
  	kgid_t gid;
  	int rc;
  
  	rc = get_option_ul(args, &value);
  	if (rc)
  		return rc;
  
  	gid = make_kgid(current_user_ns(), value);
  	if (!gid_valid(gid))
  		return -EINVAL;
  
  	*result = gid;
  	return 0;
  }
8830d7e07   Sachin Prabhu   cifs: use standar...
996
997
998
999
1000
1001
  
  static int cifs_parse_security_flavors(char *value,
  				       struct smb_vol *vol)
  {
  
  	substring_t args[MAX_OPT_ARGS];
1e3cc57e4   Jeff Layton   add new fields to...
1002
1003
1004
1005
1006
1007
  	/*
  	 * With mount options, the last one should win. Reset any existing
  	 * settings back to default.
  	 */
  	vol->sectype = Unspecified;
  	vol->sign = false;
8830d7e07   Sachin Prabhu   cifs: use standar...
1008
  	switch (match_token(value, cifs_secflavor_tokens, args)) {
3f618223d   Jeff Layton   move sectype to t...
1009
1010
1011
1012
1013
1014
1015
  	case Opt_sec_krb5p:
  		cifs_dbg(VFS, "sec=krb5p is not supported!
  ");
  		return 1;
  	case Opt_sec_krb5i:
  		vol->sign = true;
  		/* Fallthrough */
8830d7e07   Sachin Prabhu   cifs: use standar...
1016
  	case Opt_sec_krb5:
1e3cc57e4   Jeff Layton   add new fields to...
1017
  		vol->sectype = Kerberos;
8830d7e07   Sachin Prabhu   cifs: use standar...
1018
  		break;
3f618223d   Jeff Layton   move sectype to t...
1019
  	case Opt_sec_ntlmsspi:
1e3cc57e4   Jeff Layton   add new fields to...
1020
  		vol->sign = true;
3f618223d   Jeff Layton   move sectype to t...
1021
  		/* Fallthrough */
8830d7e07   Sachin Prabhu   cifs: use standar...
1022
  	case Opt_sec_ntlmssp:
1e3cc57e4   Jeff Layton   add new fields to...
1023
  		vol->sectype = RawNTLMSSP;
8830d7e07   Sachin Prabhu   cifs: use standar...
1024
  		break;
3f618223d   Jeff Layton   move sectype to t...
1025
  	case Opt_sec_ntlmi:
1e3cc57e4   Jeff Layton   add new fields to...
1026
  		vol->sign = true;
3f618223d   Jeff Layton   move sectype to t...
1027
  		/* Fallthrough */
8830d7e07   Sachin Prabhu   cifs: use standar...
1028
  	case Opt_ntlm:
1e3cc57e4   Jeff Layton   add new fields to...
1029
  		vol->sectype = NTLM;
8830d7e07   Sachin Prabhu   cifs: use standar...
1030
  		break;
3f618223d   Jeff Layton   move sectype to t...
1031
  	case Opt_sec_ntlmv2i:
1e3cc57e4   Jeff Layton   add new fields to...
1032
  		vol->sign = true;
3f618223d   Jeff Layton   move sectype to t...
1033
  		/* Fallthrough */
7659624ff   Jeff Layton   cifs: reinstate s...
1034
  	case Opt_sec_ntlmv2:
1e3cc57e4   Jeff Layton   add new fields to...
1035
  		vol->sectype = NTLMv2;
8830d7e07   Sachin Prabhu   cifs: use standar...
1036
1037
1038
  		break;
  #ifdef CONFIG_CIFS_WEAK_PW_HASH
  	case Opt_sec_lanman:
1e3cc57e4   Jeff Layton   add new fields to...
1039
  		vol->sectype = LANMAN;
8830d7e07   Sachin Prabhu   cifs: use standar...
1040
1041
1042
1043
1044
1045
  		break;
  #endif
  	case Opt_sec_none:
  		vol->nullauth = 1;
  		break;
  	default:
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1046
1047
  		cifs_dbg(VFS, "bad security option: %s
  ", value);
8830d7e07   Sachin Prabhu   cifs: use standar...
1048
1049
1050
1051
1052
  		return 1;
  	}
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1053
  static int
15b6a4732   Jeff Layton   cifs: add a cache...
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
  cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
  {
  	substring_t args[MAX_OPT_ARGS];
  
  	switch (match_token(value, cifs_cacheflavor_tokens, args)) {
  	case Opt_cache_loose:
  		vol->direct_io = false;
  		vol->strict_io = false;
  		break;
  	case Opt_cache_strict:
  		vol->direct_io = false;
  		vol->strict_io = true;
  		break;
  	case Opt_cache_none:
  		vol->direct_io = true;
  		vol->strict_io = false;
  		break;
  	default:
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1072
1073
  		cifs_dbg(VFS, "bad cache= option: %s
  ", value);
15b6a4732   Jeff Layton   cifs: add a cache...
1074
1075
1076
1077
1078
1079
  		return 1;
  	}
  	return 0;
  }
  
  static int
23db65f51   Jeff Layton   cifs: add a smb_v...
1080
1081
1082
1083
1084
1085
1086
1087
1088
  cifs_parse_smb_version(char *value, struct smb_vol *vol)
  {
  	substring_t args[MAX_OPT_ARGS];
  
  	switch (match_token(value, cifs_smb_version_tokens, args)) {
  	case Smb_1:
  		vol->ops = &smb1_operations;
  		vol->vals = &smb1_values;
  		break;
1080ef758   Steve French   CIFS: Introduce S...
1089
  #ifdef CONFIG_CIFS_SMB2
dd446b16e   Steve French   Add SMB2.02 diale...
1090
  	case Smb_20:
53ef1016f   Pavel Shilovsky   CIFS: Store lease...
1091
  		vol->ops = &smb20_operations;
dd446b16e   Steve French   Add SMB2.02 diale...
1092
1093
  		vol->vals = &smb20_values;
  		break;
1080ef758   Steve French   CIFS: Introduce S...
1094
1095
1096
1097
  	case Smb_21:
  		vol->ops = &smb21_operations;
  		vol->vals = &smb21_values;
  		break;
e4aa25e78   Steve French   [CIFS] Fix SMB2 n...
1098
  	case Smb_30:
38107d45c   Steve French   Do not send SMB2 ...
1099
  		vol->ops = &smb30_operations;
e4aa25e78   Steve French   [CIFS] Fix SMB2 n...
1100
1101
  		vol->vals = &smb30_values;
  		break;
20b6d8b42   Steve French   Add SMB3.02 diale...
1102
1103
1104
1105
  	case Smb_302:
  		vol->ops = &smb30_operations; /* currently identical with 3.0 */
  		vol->vals = &smb302_values;
  		break;
5f7fbf733   Steve French   Allow parsing ver...
1106
1107
  #ifdef CONFIG_CIFS_SMB311
  	case Smb_311:
aab1893d5   Steve French   Add SMB3.11 mount...
1108
  		vol->ops = &smb311_operations;
5f7fbf733   Steve French   Allow parsing ver...
1109
1110
1111
  		vol->vals = &smb311_values;
  		break;
  #endif /* SMB311 */
1080ef758   Steve French   CIFS: Introduce S...
1112
  #endif
23db65f51   Jeff Layton   cifs: add a smb_v...
1113
  	default:
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1114
1115
  		cifs_dbg(VFS, "Unknown vers= option specified: %s
  ", value);
23db65f51   Jeff Layton   cifs: add a smb_v...
1116
1117
1118
1119
  		return 1;
  	}
  	return 0;
  }
d387a5c50   Jeff Layton   cifs: parse the d...
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
  /*
   * Parse a devname into substrings and populate the vol->UNC and vol->prepath
   * fields with the result. Returns 0 on success and an error otherwise.
   */
  static int
  cifs_parse_devname(const char *devname, struct smb_vol *vol)
  {
  	char *pos;
  	const char *delims = "/\\";
  	size_t len;
  
  	/* make sure we have a valid UNC double delimiter prefix */
  	len = strspn(devname, delims);
  	if (len != 2)
  		return -EINVAL;
  
  	/* find delimiter between host and sharename */
  	pos = strpbrk(devname + 2, delims);
  	if (!pos)
  		return -EINVAL;
  
  	/* skip past delimiter */
  	++pos;
  
  	/* now go until next delimiter or end of string */
  	len = strcspn(pos, delims);
  
  	/* move "pos" up to delimiter or NULL */
  	pos += len;
  	vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
  	if (!vol->UNC)
  		return -ENOMEM;
  
  	convert_delimiter(vol->UNC, '\\');
11e31647c   Sachin Prabhu   cifs: remove any ...
1154
1155
1156
1157
1158
1159
  	/* skip any delimiter */
  	if (*pos == '/' || *pos == '\\')
  		pos++;
  
  	/* If pos is NULL then no prepath */
  	if (!*pos)
d387a5c50   Jeff Layton   cifs: parse the d...
1160
1161
1162
1163
1164
1165
1166
1167
  		return 0;
  
  	vol->prepath = kstrdup(pos, GFP_KERNEL);
  	if (!vol->prepath)
  		return -ENOMEM;
  
  	return 0;
  }
23db65f51   Jeff Layton   cifs: add a smb_v...
1168
  static int
b946845a9   Sean Finney   cifs: cifs_parse_...
1169
  cifs_parse_mount_options(const char *mountdata, const char *devname,
50c2f7538   Steve French   [CIFS] whitespace...
1170
  			 struct smb_vol *vol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1171
  {
8830d7e07   Sachin Prabhu   cifs: use standar...
1172
  	char *data, *end;
957df4535   Vasily Averin   possible memory c...
1173
  	char *mountdata_copy = NULL, *options;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1174
1175
  	unsigned int  temp_len, i, j;
  	char separator[2];
9b9d6b243   Jeff Layton   cifs: reinstate o...
1176
1177
1178
1179
  	short int override_uid = -1;
  	short int override_gid = -1;
  	bool uid_specified = false;
  	bool gid_specified = false;
d81625587   Jeff Layton   cifs: handle "slo...
1180
1181
  	bool sloppy = false;
  	char *invalid = NULL;
884639996   Jeff Layton   cifs: remove Loca...
1182
  	char *nodename = utsname()->nodename;
8830d7e07   Sachin Prabhu   cifs: use standar...
1183
1184
1185
  	char *string = NULL;
  	char *tmp_end, *value;
  	char delim;
b979aaa17   Jeff Layton   cifs: get rid of ...
1186
1187
1188
  	bool got_ip = false;
  	unsigned short port = 0;
  	struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1189
1190
  
  	separator[0] = ',';
50c2f7538   Steve French   [CIFS] whitespace...
1191
  	separator[1] = 0;
8830d7e07   Sachin Prabhu   cifs: use standar...
1192
  	delim = separator[0];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1193

6ee9542a8   Jeff Layton   cifs: always zero...
1194
1195
  	/* ensure we always start with zeroed-out smb_vol */
  	memset(vol, 0, sizeof(*vol));
884639996   Jeff Layton   cifs: remove Loca...
1196
1197
1198
1199
1200
  	/*
  	 * does not have to be perfect mapping since field is
  	 * informational, only used for servers that do not support
  	 * port 445 and it can be overridden at mount time
  	 */
1397f2ee4   Jeff Layton   cifs: replace som...
1201
1202
  	memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
  	for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
884639996   Jeff Layton   cifs: remove Loca...
1203
  		vol->source_rfc1001_name[i] = toupper(nodename[i]);
1397f2ee4   Jeff Layton   cifs: replace som...
1204
  	vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
a10faeb2a   Steve French   [CIFS] Support fo...
1205
1206
1207
  	/* null target name indicates to use *SMBSERVR default called name
  	   if we end up sending RFC1001 session initialize */
  	vol->target_rfc1001_name[0] = 0;
3e4b3e1f6   Jeff Layton   cifs: add separat...
1208
1209
  	vol->cred_uid = current_uid();
  	vol->linux_uid = current_uid();
a001e5b55   David Howells   CRED: Wrap task c...
1210
  	vol->linux_gid = current_gid();
f55ed1a83   Jeff Layton   cifs: tighten up ...
1211

2baa26825   Steve French   Remap reserved po...
1212
1213
1214
1215
1216
1217
1218
  	/*
  	 * default to SFM style remapping of seven reserved characters
  	 * unless user overrides it or we negotiate CIFS POSIX where
  	 * it is unnecessary.  Can not simultaneously use more than one mapping
  	 * since then readdir could list files that open could not open
  	 */
  	vol->remap = true;
f55ed1a83   Jeff Layton   cifs: tighten up ...
1219
1220
  	/* default to only allowing write access to owner of the mount */
  	vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1221
1222
  
  	/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
1223
1224
  	/* default is always to request posix paths. */
  	vol->posix_paths = 1;
a0c9217f6   Jeff Layton   cifs: make server...
1225
1226
  	/* default to using server inode numbers where available */
  	vol->server_ino = 1;
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
1227

1b3592049   Jeff Layton   cifs: remove supp...
1228
1229
  	/* default is to use strict cifs caching semantics */
  	vol->strict_io = true;
6d20e8406   Suresh Jayaraman   cifs: add attribu...
1230
  	vol->actimeo = CIFS_DEF_ACTIMEO;
23db65f51   Jeff Layton   cifs: add a smb_v...
1231
1232
1233
  	/* FIXME: add autonegotiation -- for now, SMB1 is default */
  	vol->ops = &smb1_operations;
  	vol->vals = &smb1_values;
b782fcc1c   Rabin Vincent   cifs: unbreak TCP...
1234
  	vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
b946845a9   Sean Finney   cifs: cifs_parse_...
1235
1236
1237
1238
1239
1240
  	if (!mountdata)
  		goto cifs_parse_mount_err;
  
  	mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
  	if (!mountdata_copy)
  		goto cifs_parse_mount_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1241

b946845a9   Sean Finney   cifs: cifs_parse_...
1242
  	options = mountdata_copy;
4906e50b3   Pavel Shilovsky   CIFS: Fix memory ...
1243
  	end = options + strlen(options);
8830d7e07   Sachin Prabhu   cifs: use standar...
1244

50c2f7538   Steve French   [CIFS] whitespace...
1245
  	if (strncmp(options, "sep=", 4) == 0) {
fb8c4b14d   Steve French   [CIFS] whitespace...
1246
  		if (options[4] != 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1247
1248
1249
  			separator[0] = options[4];
  			options += 5;
  		} else {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1250
1251
  			cifs_dbg(FYI, "Null separator not allowed
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1252
1253
  		}
  	}
3d3ea8e64   Shirish Pargaonkar   cifs: Add mount o...
1254
1255
  	vol->backupuid_specified = false; /* no backup intent for a user */
  	vol->backupgid_specified = false; /* no backup intent for a group */
50c2f7538   Steve French   [CIFS] whitespace...
1256

37d4f99b5   Jeff Layton   cifs: fix error h...
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
  	switch (cifs_parse_devname(devname, vol)) {
  	case 0:
  		break;
  	case -ENOMEM:
  		cifs_dbg(VFS, "Unable to allocate memory for devname.
  ");
  		goto cifs_parse_mount_err;
  	case -EINVAL:
  		cifs_dbg(VFS, "Malformed UNC in devname.
  ");
  		goto cifs_parse_mount_err;
  	default:
  		cifs_dbg(VFS, "Unknown error parsing devname.
  ");
  		goto cifs_parse_mount_err;
d387a5c50   Jeff Layton   cifs: parse the d...
1272
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1273
  	while ((data = strsep(&options, separator)) != NULL) {
8830d7e07   Sachin Prabhu   cifs: use standar...
1274
1275
1276
  		substring_t args[MAX_OPT_ARGS];
  		unsigned long option;
  		int token;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1277
1278
  		if (!*data)
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1279

8830d7e07   Sachin Prabhu   cifs: use standar...
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
  		token = match_token(data, cifs_mount_option_tokens, args);
  
  		switch (token) {
  
  		/* Ingnore the following */
  		case Opt_ignore:
  			break;
  
  		/* Boolean values */
  		case Opt_user_xattr:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1290
  			vol->no_xattr = 0;
8830d7e07   Sachin Prabhu   cifs: use standar...
1291
1292
  			break;
  		case Opt_nouser_xattr:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1293
  			vol->no_xattr = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1294
1295
  			break;
  		case Opt_forceuid:
9b9d6b243   Jeff Layton   cifs: reinstate o...
1296
  			override_uid = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1297
1298
  			break;
  		case Opt_noforceuid:
9b9d6b243   Jeff Layton   cifs: reinstate o...
1299
  			override_uid = 0;
8830d7e07   Sachin Prabhu   cifs: use standar...
1300
  			break;
72bd481f8   Jeff Layton   cifs: reinstate t...
1301
1302
1303
1304
1305
1306
  		case Opt_forcegid:
  			override_gid = 1;
  			break;
  		case Opt_noforcegid:
  			override_gid = 0;
  			break;
8830d7e07   Sachin Prabhu   cifs: use standar...
1307
  		case Opt_noblocksend:
edf1ae403   Steve French   [CIFS] Reduce num...
1308
  			vol->noblocksnd = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1309
1310
  			break;
  		case Opt_noautotune:
edf1ae403   Steve French   [CIFS] Reduce num...
1311
  			vol->noautotune = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1312
1313
  			break;
  		case Opt_hard:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1314
  			vol->retry = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1315
1316
  			break;
  		case Opt_soft:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1317
  			vol->retry = 0;
8830d7e07   Sachin Prabhu   cifs: use standar...
1318
1319
  			break;
  		case Opt_perm:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1320
  			vol->noperm = 0;
8830d7e07   Sachin Prabhu   cifs: use standar...
1321
1322
  			break;
  		case Opt_noperm:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1323
  			vol->noperm = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1324
1325
  			break;
  		case Opt_mapchars:
2baa26825   Steve French   Remap reserved po...
1326
1327
  			vol->sfu_remap = true;
  			vol->remap = false; /* disable SFM mapping */
8830d7e07   Sachin Prabhu   cifs: use standar...
1328
1329
  			break;
  		case Opt_nomapchars:
2baa26825   Steve French   Remap reserved po...
1330
1331
1332
1333
1334
1335
1336
1337
  			vol->sfu_remap = false;
  			break;
  		case Opt_mapposix:
  			vol->remap = true;
  			vol->sfu_remap = false; /* disable SFU mapping */
  			break;
  		case Opt_nomapposix:
  			vol->remap = false;
8830d7e07   Sachin Prabhu   cifs: use standar...
1338
1339
  			break;
  		case Opt_sfu:
50c2f7538   Steve French   [CIFS] whitespace...
1340
  			vol->sfu_emul = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1341
1342
  			break;
  		case Opt_nosfu:
50c2f7538   Steve French   [CIFS] whitespace...
1343
  			vol->sfu_emul = 0;
8830d7e07   Sachin Prabhu   cifs: use standar...
1344
1345
  			break;
  		case Opt_nodfs:
2c1b86153   Steve French   [CIFS] Add nodfs ...
1346
  			vol->nodfs = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1347
1348
  			break;
  		case Opt_posixpaths:
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
1349
  			vol->posix_paths = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1350
1351
  			break;
  		case Opt_noposixpaths:
ac67055ef   Jeremy Allison   [CIFS] POSIX exte...
1352
  			vol->posix_paths = 0;
8830d7e07   Sachin Prabhu   cifs: use standar...
1353
1354
  			break;
  		case Opt_nounix:
c18c842b1   Steve French   [CIFS] Allow disa...
1355
  			vol->no_linux_ext = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1356
1357
  			break;
  		case Opt_nocase:
50c2f7538   Steve French   [CIFS] whitespace...
1358
  			vol->nocase = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1359
1360
  			break;
  		case Opt_brl:
c46fa8acd   Steve French   [CIFS] Add mount ...
1361
  			vol->nobrl =  0;
8830d7e07   Sachin Prabhu   cifs: use standar...
1362
1363
  			break;
  		case Opt_nobrl:
c46fa8acd   Steve French   [CIFS] Add mount ...
1364
  			vol->nobrl =  1;
5cfdddcfc   Pavel Shilovsky   CIFS: Add missed ...
1365
1366
  			/*
  			 * turn off mandatory locking in mode
8830d7e07   Sachin Prabhu   cifs: use standar...
1367
  			 * if remote locking is turned off since the
5cfdddcfc   Pavel Shilovsky   CIFS: Add missed ...
1368
1369
  			 * local vfs will do advisory
  			 */
50c2f7538   Steve French   [CIFS] whitespace...
1370
1371
  			if (vol->file_mode ==
  				(S_IALLUGO & ~(S_ISUID | S_IXGRP)))
d3485d37c   Steve French   [CIFS] Finish cif...
1372
  				vol->file_mode = S_IALLUGO;
8830d7e07   Sachin Prabhu   cifs: use standar...
1373
1374
  			break;
  		case Opt_forcemandatorylock:
13a6e42af   Steve French   [CIFS] add mount ...
1375
  			vol->mand_lock = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1376
1377
  			break;
  		case Opt_setuids:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1378
  			vol->setuids = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1379
1380
  			break;
  		case Opt_nosetuids:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1381
  			vol->setuids = 0;
8830d7e07   Sachin Prabhu   cifs: use standar...
1382
  			break;
959326553   Steve French   CIFS: Add new mou...
1383
1384
1385
  		case Opt_setuidfromacl:
  			vol->setuidfromacl = 1;
  			break;
8830d7e07   Sachin Prabhu   cifs: use standar...
1386
  		case Opt_dynperm:
d0a9c078d   Jeff Layton   [CIFS] CIFS curre...
1387
  			vol->dynperm = true;
8830d7e07   Sachin Prabhu   cifs: use standar...
1388
1389
  			break;
  		case Opt_nodynperm:
d0a9c078d   Jeff Layton   [CIFS] CIFS curre...
1390
  			vol->dynperm = false;
8830d7e07   Sachin Prabhu   cifs: use standar...
1391
1392
  			break;
  		case Opt_nohard:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1393
  			vol->retry = 0;
8830d7e07   Sachin Prabhu   cifs: use standar...
1394
1395
  			break;
  		case Opt_nosoft:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1396
  			vol->retry = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1397
1398
  			break;
  		case Opt_nointr:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1399
  			vol->intr = 0;
8830d7e07   Sachin Prabhu   cifs: use standar...
1400
1401
  			break;
  		case Opt_intr:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1402
  			vol->intr = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1403
1404
  			break;
  		case Opt_nostrictsync:
be652445f   Steve French   [CIFS] Add new no...
1405
  			vol->nostrictsync = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1406
1407
  			break;
  		case Opt_strictsync:
be652445f   Steve French   [CIFS] Add new no...
1408
  			vol->nostrictsync = 0;
8830d7e07   Sachin Prabhu   cifs: use standar...
1409
1410
  			break;
  		case Opt_serverino:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1411
  			vol->server_ino = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1412
1413
  			break;
  		case Opt_noserverino:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1414
  			vol->server_ino = 0;
8830d7e07   Sachin Prabhu   cifs: use standar...
1415
1416
  			break;
  		case Opt_rwpidforward:
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
1417
  			vol->rwpidforward = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1418
1419
  			break;
  		case Opt_cifsacl:
0a4b92c05   Steve French   [CIFS] Add worker...
1420
  			vol->cifs_acl = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1421
1422
  			break;
  		case Opt_nocifsacl:
0a4b92c05   Steve French   [CIFS] Add worker...
1423
  			vol->cifs_acl = 0;
8830d7e07   Sachin Prabhu   cifs: use standar...
1424
1425
  			break;
  		case Opt_acl:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1426
  			vol->no_psx_acl = 0;
8830d7e07   Sachin Prabhu   cifs: use standar...
1427
1428
  			break;
  		case Opt_noacl:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1429
  			vol->no_psx_acl = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1430
1431
  			break;
  		case Opt_locallease:
84210e912   Steve French   [CIFS] improve se...
1432
  			vol->local_lease = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1433
1434
  			break;
  		case Opt_sign:
1e3cc57e4   Jeff Layton   add new fields to...
1435
  			vol->sign = true;
8830d7e07   Sachin Prabhu   cifs: use standar...
1436
1437
  			break;
  		case Opt_seal:
95b1cb90b   Steve French   [CIFS] enable par...
1438
  			/* we do not do the following in secFlags because seal
8830d7e07   Sachin Prabhu   cifs: use standar...
1439
1440
1441
1442
  			 * is a per tree connection (mount) not a per socket
  			 * or per-smb connection option in the protocol
  			 * vol->secFlg |= CIFSSEC_MUST_SEAL;
  			 */
95b1cb90b   Steve French   [CIFS] enable par...
1443
  			vol->seal = 1;
8830d7e07   Sachin Prabhu   cifs: use standar...
1444
  			break;
8830d7e07   Sachin Prabhu   cifs: use standar...
1445
  		case Opt_noac:
0b456f04b   Andy Shevchenko   cifs: convert pri...
1446
1447
  			pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0
  ");
8830d7e07   Sachin Prabhu   cifs: use standar...
1448
1449
  			break;
  		case Opt_fsc:
607a569da   Suresh Jayaraman   cifs: allow fsc m...
1450
  #ifndef CONFIG_CIFS_FSCACHE
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1451
1452
  			cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1453
  			goto cifs_parse_mount_err;
607a569da   Suresh Jayaraman   cifs: allow fsc m...
1454
  #endif
fa1df75d4   Suresh Jayaraman   cifs: add mount o...
1455
  			vol->fsc = true;
8830d7e07   Sachin Prabhu   cifs: use standar...
1456
1457
  			break;
  		case Opt_mfsymlinks:
736a33205   Stefan Metzmacher   cifs: add "mfsyml...
1458
  			vol->mfsymlinks = true;
8830d7e07   Sachin Prabhu   cifs: use standar...
1459
1460
  			break;
  		case Opt_multiuser:
0eb8a132c   Jeff Layton   cifs: add "multiu...
1461
  			vol->multiuser = true;
8830d7e07   Sachin Prabhu   cifs: use standar...
1462
  			break;
d81625587   Jeff Layton   cifs: handle "slo...
1463
1464
1465
  		case Opt_sloppy:
  			sloppy = true;
  			break;
a0b3df5cf   Jeff Layton   cifs: add a "nosh...
1466
1467
1468
  		case Opt_nosharesock:
  			vol->nosharesock = true;
  			break;
b2a307741   Steve French   [SMB3] Add parsin...
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
  		case Opt_nopersistent:
  			vol->nopersistent = true;
  			if (vol->persistent) {
  				cifs_dbg(VFS,
  				  "persistenthandles mount options conflict
  ");
  				goto cifs_parse_mount_err;
  			}
  			break;
  		case Opt_persistent:
  			vol->persistent = true;
592fafe64   Steve French   Add resilienthand...
1480
  			if ((vol->nopersistent) || (vol->resilient)) {
b2a307741   Steve French   [SMB3] Add parsin...
1481
1482
1483
1484
1485
1486
  				cifs_dbg(VFS,
  				  "persistenthandles mount options conflict
  ");
  				goto cifs_parse_mount_err;
  			}
  			break;
592fafe64   Steve French   Add resilienthand...
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
  		case Opt_resilient:
  			vol->resilient = true;
  			if (vol->persistent) {
  				cifs_dbg(VFS,
  				  "persistenthandles mount options conflict
  ");
  				goto cifs_parse_mount_err;
  			}
  			break;
  		case Opt_noresilient:
  			vol->resilient = false; /* already the default */
  			break;
8830d7e07   Sachin Prabhu   cifs: use standar...
1499
1500
1501
  
  		/* Numeric Values */
  		case Opt_backupuid:
3da465650   Eric W. Biederman   cifs: Modify stru...
1502
  			if (get_option_uid(args, &vol->backupuid)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1503
1504
1505
  				cifs_dbg(VFS, "%s: Invalid backupuid value
  ",
  					 __func__);
3d3ea8e64   Shirish Pargaonkar   cifs: Add mount o...
1506
1507
1508
  				goto cifs_parse_mount_err;
  			}
  			vol->backupuid_specified = true;
8830d7e07   Sachin Prabhu   cifs: use standar...
1509
1510
  			break;
  		case Opt_backupgid:
3da465650   Eric W. Biederman   cifs: Modify stru...
1511
  			if (get_option_gid(args, &vol->backupgid)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1512
1513
1514
  				cifs_dbg(VFS, "%s: Invalid backupgid value
  ",
  					 __func__);
3d3ea8e64   Shirish Pargaonkar   cifs: Add mount o...
1515
1516
1517
  				goto cifs_parse_mount_err;
  			}
  			vol->backupgid_specified = true;
8830d7e07   Sachin Prabhu   cifs: use standar...
1518
1519
  			break;
  		case Opt_uid:
3da465650   Eric W. Biederman   cifs: Modify stru...
1520
  			if (get_option_uid(args, &vol->linux_uid)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1521
1522
1523
  				cifs_dbg(VFS, "%s: Invalid uid value
  ",
  					 __func__);
8830d7e07   Sachin Prabhu   cifs: use standar...
1524
1525
  				goto cifs_parse_mount_err;
  			}
8830d7e07   Sachin Prabhu   cifs: use standar...
1526
1527
1528
  			uid_specified = true;
  			break;
  		case Opt_cruid:
3da465650   Eric W. Biederman   cifs: Modify stru...
1529
  			if (get_option_uid(args, &vol->cred_uid)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1530
1531
1532
  				cifs_dbg(VFS, "%s: Invalid cruid value
  ",
  					 __func__);
8830d7e07   Sachin Prabhu   cifs: use standar...
1533
1534
  				goto cifs_parse_mount_err;
  			}
8830d7e07   Sachin Prabhu   cifs: use standar...
1535
1536
  			break;
  		case Opt_gid:
3da465650   Eric W. Biederman   cifs: Modify stru...
1537
  			if (get_option_gid(args, &vol->linux_gid)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1538
1539
1540
  				cifs_dbg(VFS, "%s: Invalid gid value
  ",
  					 __func__);
8830d7e07   Sachin Prabhu   cifs: use standar...
1541
1542
  				goto cifs_parse_mount_err;
  			}
8830d7e07   Sachin Prabhu   cifs: use standar...
1543
1544
1545
1546
  			gid_specified = true;
  			break;
  		case Opt_file_mode:
  			if (get_option_ul(args, &option)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1547
1548
1549
  				cifs_dbg(VFS, "%s: Invalid file_mode value
  ",
  					 __func__);
8830d7e07   Sachin Prabhu   cifs: use standar...
1550
1551
1552
1553
1554
1555
  				goto cifs_parse_mount_err;
  			}
  			vol->file_mode = option;
  			break;
  		case Opt_dirmode:
  			if (get_option_ul(args, &option)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1556
1557
1558
  				cifs_dbg(VFS, "%s: Invalid dir_mode value
  ",
  					 __func__);
8830d7e07   Sachin Prabhu   cifs: use standar...
1559
1560
1561
1562
1563
  				goto cifs_parse_mount_err;
  			}
  			vol->dir_mode = option;
  			break;
  		case Opt_port:
b979aaa17   Jeff Layton   cifs: get rid of ...
1564
1565
  			if (get_option_ul(args, &option) ||
  			    option > USHRT_MAX) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1566
1567
1568
  				cifs_dbg(VFS, "%s: Invalid port value
  ",
  					 __func__);
8830d7e07   Sachin Prabhu   cifs: use standar...
1569
1570
  				goto cifs_parse_mount_err;
  			}
b979aaa17   Jeff Layton   cifs: get rid of ...
1571
  			port = (unsigned short)option;
8830d7e07   Sachin Prabhu   cifs: use standar...
1572
1573
1574
  			break;
  		case Opt_rsize:
  			if (get_option_ul(args, &option)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1575
1576
1577
  				cifs_dbg(VFS, "%s: Invalid rsize value
  ",
  					 __func__);
b946845a9   Sean Finney   cifs: cifs_parse_...
1578
  				goto cifs_parse_mount_err;
8830d7e07   Sachin Prabhu   cifs: use standar...
1579
1580
1581
1582
1583
  			}
  			vol->rsize = option;
  			break;
  		case Opt_wsize:
  			if (get_option_ul(args, &option)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1584
1585
1586
  				cifs_dbg(VFS, "%s: Invalid wsize value
  ",
  					 __func__);
8830d7e07   Sachin Prabhu   cifs: use standar...
1587
1588
1589
1590
1591
1592
  				goto cifs_parse_mount_err;
  			}
  			vol->wsize = option;
  			break;
  		case Opt_actimeo:
  			if (get_option_ul(args, &option)) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1593
1594
1595
  				cifs_dbg(VFS, "%s: Invalid actimeo value
  ",
  					 __func__);
8830d7e07   Sachin Prabhu   cifs: use standar...
1596
1597
1598
1599
  				goto cifs_parse_mount_err;
  			}
  			vol->actimeo = HZ * option;
  			if (vol->actimeo > CIFS_MAX_ACTIMEO) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1600
1601
  				cifs_dbg(VFS, "attribute cache timeout too large
  ");
8830d7e07   Sachin Prabhu   cifs: use standar...
1602
1603
1604
  				goto cifs_parse_mount_err;
  			}
  			break;
adfeb3e00   Steve French   cifs: Make echo i...
1605
1606
1607
1608
1609
1610
1611
1612
1613
  		case Opt_echo_interval:
  			if (get_option_ul(args, &option)) {
  				cifs_dbg(VFS, "%s: Invalid echo interval value
  ",
  					 __func__);
  				goto cifs_parse_mount_err;
  			}
  			vol->echo_interval = option;
  			break;
141891f47   Steve French   SMB3: Add mount p...
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
  		case Opt_max_credits:
  			if (get_option_ul(args, &option) || (option < 20) ||
  			    (option > 60000)) {
  				cifs_dbg(VFS, "%s: Invalid max_credits value
  ",
  					 __func__);
  				goto cifs_parse_mount_err;
  			}
  			vol->max_credits = option;
  			break;
8830d7e07   Sachin Prabhu   cifs: use standar...
1624
1625
  
  		/* String Arguments */
4fe9e9639   Sachin Prabhu   Cleanup handling ...
1626
1627
1628
1629
1630
  		case Opt_blank_user:
  			/* null user, ie. anonymous authentication */
  			vol->nullauth = 1;
  			vol->username = NULL;
  			break;
8830d7e07   Sachin Prabhu   cifs: use standar...
1631
1632
1633
1634
  		case Opt_user:
  			string = match_strdup(args);
  			if (string == NULL)
  				goto out_nomem;
8c3a2b4c4   Scott Lovenberg   cifs: Move string...
1635
1636
  			if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
  							CIFS_MAX_USERNAME_LEN) {
0b456f04b   Andy Shevchenko   cifs: convert pri...
1637
1638
  				pr_warn("CIFS: username too long
  ");
8830d7e07   Sachin Prabhu   cifs: use standar...
1639
1640
  				goto cifs_parse_mount_err;
  			}
2bd50fb3d   Taesoo Kim   cifs: potential m...
1641
1642
  
  			kfree(vol->username);
8830d7e07   Sachin Prabhu   cifs: use standar...
1643
  			vol->username = kstrdup(string, GFP_KERNEL);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1644
  			if (!vol->username)
8830d7e07   Sachin Prabhu   cifs: use standar...
1645
  				goto cifs_parse_mount_err;
8830d7e07   Sachin Prabhu   cifs: use standar...
1646
1647
  			break;
  		case Opt_blank_pass:
8830d7e07   Sachin Prabhu   cifs: use standar...
1648
1649
1650
1651
  			/* passwords have to be handled differently
  			 * to allow the character used for deliminator
  			 * to be passed within them
  			 */
c369c9a4a   Sachin Prabhu   cifs: Allow passw...
1652
1653
1654
1655
1656
1657
1658
1659
  			/*
  			 * Check if this is a case where the  password
  			 * starts with a delimiter
  			 */
  			tmp_end = strchr(data, '=');
  			tmp_end++;
  			if (!(tmp_end < end && tmp_end[1] == delim)) {
  				/* No it is not. Set the password to NULL */
d6ccf4997   Namjae Jeon   cifs: fix memory ...
1660
  				kfree(vol->password);
c369c9a4a   Sachin Prabhu   cifs: Allow passw...
1661
1662
1663
1664
1665
  				vol->password = NULL;
  				break;
  			}
  			/* Yes it is. Drop down to Opt_pass below.*/
  		case Opt_pass:
8830d7e07   Sachin Prabhu   cifs: use standar...
1666
1667
  			/* Obtain the value string */
  			value = strchr(data, '=');
102380745   Sachin Prabhu   Remove unnecessar...
1668
  			value++;
8830d7e07   Sachin Prabhu   cifs: use standar...
1669
1670
1671
1672
1673
1674
1675
1676
  
  			/* Set tmp_end to end of the string */
  			tmp_end = (char *) value + strlen(value);
  
  			/* Check if following character is the deliminator
  			 * If yes, we have encountered a double deliminator
  			 * reset the NULL character to the deliminator
  			 */
e73f843a3   Suresh Jayaraman   cifs: fix parsing...
1677
  			if (tmp_end < end && tmp_end[1] == delim) {
8830d7e07   Sachin Prabhu   cifs: use standar...
1678
  				tmp_end[0] = delim;
e73f843a3   Suresh Jayaraman   cifs: fix parsing...
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
  				/* Keep iterating until we get to a single
  				 * deliminator OR the end
  				 */
  				while ((tmp_end = strchr(tmp_end, delim))
  					!= NULL && (tmp_end[1] == delim)) {
  						tmp_end = (char *) &tmp_end[2];
  				}
  
  				/* Reset var options to point to next element */
  				if (tmp_end) {
  					tmp_end[0] = '\0';
  					options = (char *) &tmp_end[1];
  				} else
  					/* Reached the end of the mount option
  					 * string */
  					options = end;
8830d7e07   Sachin Prabhu   cifs: use standar...
1695
  			}
d6ccf4997   Namjae Jeon   cifs: fix memory ...
1696
  			kfree(vol->password);
8830d7e07   Sachin Prabhu   cifs: use standar...
1697
1698
1699
1700
  			/* Now build new password string */
  			temp_len = strlen(value);
  			vol->password = kzalloc(temp_len+1, GFP_KERNEL);
  			if (vol->password == NULL) {
0b456f04b   Andy Shevchenko   cifs: convert pri...
1701
1702
  				pr_warn("CIFS: no memory for password
  ");
8830d7e07   Sachin Prabhu   cifs: use standar...
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
  				goto cifs_parse_mount_err;
  			}
  
  			for (i = 0, j = 0; i < temp_len; i++, j++) {
  				vol->password[j] = value[i];
  				if ((value[i] == delim) &&
  				     value[i+1] == delim)
  					/* skip the second deliminator */
  					i++;
  			}
  			vol->password[j] = '\0';
  			break;
4fe9e9639   Sachin Prabhu   Cleanup handling ...
1715
  		case Opt_blank_ip:
b979aaa17   Jeff Layton   cifs: get rid of ...
1716
1717
  			/* FIXME: should this be an error instead? */
  			got_ip = false;
4fe9e9639   Sachin Prabhu   Cleanup handling ...
1718
  			break;
8830d7e07   Sachin Prabhu   cifs: use standar...
1719
1720
1721
1722
  		case Opt_ip:
  			string = match_strdup(args);
  			if (string == NULL)
  				goto out_nomem;
b979aaa17   Jeff Layton   cifs: get rid of ...
1723
1724
  			if (!cifs_convert_address(dstaddr, string,
  					strlen(string))) {
0b456f04b   Andy Shevchenko   cifs: convert pri...
1725
1726
  				pr_err("CIFS: bad ip= option (%s).
  ", string);
8830d7e07   Sachin Prabhu   cifs: use standar...
1727
1728
  				goto cifs_parse_mount_err;
  			}
b979aaa17   Jeff Layton   cifs: get rid of ...
1729
  			got_ip = true;
8830d7e07   Sachin Prabhu   cifs: use standar...
1730
  			break;
8830d7e07   Sachin Prabhu   cifs: use standar...
1731
1732
1733
1734
  		case Opt_domain:
  			string = match_strdup(args);
  			if (string == NULL)
  				goto out_nomem;
057d6332b   Chen Gang   cifs: extend the ...
1735
1736
  			if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
  					== CIFS_MAX_DOMAINNAME_LEN) {
0b456f04b   Andy Shevchenko   cifs: convert pri...
1737
1738
  				pr_warn("CIFS: domain name too long
  ");
8830d7e07   Sachin Prabhu   cifs: use standar...
1739
1740
  				goto cifs_parse_mount_err;
  			}
2bd50fb3d   Taesoo Kim   cifs: potential m...
1741
  			kfree(vol->domainname);
8830d7e07   Sachin Prabhu   cifs: use standar...
1742
1743
  			vol->domainname = kstrdup(string, GFP_KERNEL);
  			if (!vol->domainname) {
0b456f04b   Andy Shevchenko   cifs: convert pri...
1744
1745
  				pr_warn("CIFS: no memory for domainname
  ");
8830d7e07   Sachin Prabhu   cifs: use standar...
1746
1747
  				goto cifs_parse_mount_err;
  			}
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1748
1749
  			cifs_dbg(FYI, "Domain name set
  ");
8830d7e07   Sachin Prabhu   cifs: use standar...
1750
1751
1752
1753
1754
  			break;
  		case Opt_srcaddr:
  			string = match_strdup(args);
  			if (string == NULL)
  				goto out_nomem;
4fe9e9639   Sachin Prabhu   Cleanup handling ...
1755
  			if (!cifs_convert_address(
8830d7e07   Sachin Prabhu   cifs: use standar...
1756
1757
  					(struct sockaddr *)&vol->srcaddr,
  					string, strlen(string))) {
0b456f04b   Andy Shevchenko   cifs: convert pri...
1758
1759
1760
  				pr_warn("CIFS: Could not parse srcaddr: %s
  ",
  					string);
8830d7e07   Sachin Prabhu   cifs: use standar...
1761
1762
1763
  				goto cifs_parse_mount_err;
  			}
  			break;
8830d7e07   Sachin Prabhu   cifs: use standar...
1764
1765
1766
1767
  		case Opt_iocharset:
  			string = match_strdup(args);
  			if (string == NULL)
  				goto out_nomem;
4fe9e9639   Sachin Prabhu   Cleanup handling ...
1768
  			if (strnlen(string, 1024) >= 65) {
0b456f04b   Andy Shevchenko   cifs: convert pri...
1769
1770
  				pr_warn("CIFS: iocharset name too long.
  ");
8830d7e07   Sachin Prabhu   cifs: use standar...
1771
1772
  				goto cifs_parse_mount_err;
  			}
87e747cdb   Rasmus Villemoes   cifs: replace str...
1773
  			 if (strncasecmp(string, "default", 7) != 0) {
2bd50fb3d   Taesoo Kim   cifs: potential m...
1774
  				kfree(vol->iocharset);
8830d7e07   Sachin Prabhu   cifs: use standar...
1775
1776
1777
  				vol->iocharset = kstrdup(string,
  							 GFP_KERNEL);
  				if (!vol->iocharset) {
0b456f04b   Andy Shevchenko   cifs: convert pri...
1778
1779
  					pr_warn("CIFS: no memory for charset
  ");
8830d7e07   Sachin Prabhu   cifs: use standar...
1780
1781
1782
1783
1784
1785
  					goto cifs_parse_mount_err;
  				}
  			}
  			/* if iocharset not set then load_nls_default
  			 * is used by caller
  			 */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1786
1787
  			 cifs_dbg(FYI, "iocharset set to %s
  ", string);
8830d7e07   Sachin Prabhu   cifs: use standar...
1788
  			break;
8830d7e07   Sachin Prabhu   cifs: use standar...
1789
1790
1791
1792
  		case Opt_netbiosname:
  			string = match_strdup(args);
  			if (string == NULL)
  				goto out_nomem;
8830d7e07   Sachin Prabhu   cifs: use standar...
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
  			memset(vol->source_rfc1001_name, 0x20,
  				RFC1001_NAME_LEN);
  			/*
  			 * FIXME: are there cases in which a comma can
  			 * be valid in workstation netbios name (and
  			 * need special handling)?
  			 */
  			for (i = 0; i < RFC1001_NAME_LEN; i++) {
  				/* don't ucase netbiosname for user */
  				if (string[i] == 0)
  					break;
  				vol->source_rfc1001_name[i] = string[i];
  			}
  			/* The string has 16th byte zero still from
  			 * set at top of the function
  			 */
  			if (i == RFC1001_NAME_LEN && string[i] != 0)
0b456f04b   Andy Shevchenko   cifs: convert pri...
1810
1811
  				pr_warn("CIFS: netbiosname longer than 15 truncated.
  ");
8830d7e07   Sachin Prabhu   cifs: use standar...
1812
1813
1814
1815
1816
1817
  			break;
  		case Opt_servern:
  			/* servernetbiosname specified override *SMBSERVER */
  			string = match_strdup(args);
  			if (string == NULL)
  				goto out_nomem;
8830d7e07   Sachin Prabhu   cifs: use standar...
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
  			/* last byte, type, is 0x20 for servr type */
  			memset(vol->target_rfc1001_name, 0x20,
  				RFC1001_NAME_LEN_WITH_NULL);
  
  			/* BB are there cases in which a comma can be
  			   valid in this workstation netbios name
  			   (and need special handling)? */
  
  			/* user or mount helper must uppercase the
  			   netbios name */
  			for (i = 0; i < 15; i++) {
  				if (string[i] == 0)
  					break;
  				vol->target_rfc1001_name[i] = string[i];
  			}
  			/* The string has 16th byte zero still from
  			   set at top of the function  */
  			if (i == RFC1001_NAME_LEN && string[i] != 0)
0b456f04b   Andy Shevchenko   cifs: convert pri...
1836
1837
  				pr_warn("CIFS: server netbiosname longer than 15 truncated.
  ");
8830d7e07   Sachin Prabhu   cifs: use standar...
1838
1839
1840
1841
1842
  			break;
  		case Opt_ver:
  			string = match_strdup(args);
  			if (string == NULL)
  				goto out_nomem;
87e747cdb   Rasmus Villemoes   cifs: replace str...
1843
  			if (strncasecmp(string, "1", 1) == 0) {
8830d7e07   Sachin Prabhu   cifs: use standar...
1844
1845
1846
1847
  				/* This is the default */
  				break;
  			}
  			/* For all other value, error */
0b456f04b   Andy Shevchenko   cifs: convert pri...
1848
1849
  			pr_warn("CIFS: Invalid version specified
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1850
  			goto cifs_parse_mount_err;
23db65f51   Jeff Layton   cifs: add a smb_v...
1851
1852
1853
1854
1855
1856
1857
1858
  		case Opt_vers:
  			string = match_strdup(args);
  			if (string == NULL)
  				goto out_nomem;
  
  			if (cifs_parse_smb_version(string, vol) != 0)
  				goto cifs_parse_mount_err;
  			break;
8830d7e07   Sachin Prabhu   cifs: use standar...
1859
1860
1861
1862
  		case Opt_sec:
  			string = match_strdup(args);
  			if (string == NULL)
  				goto out_nomem;
8830d7e07   Sachin Prabhu   cifs: use standar...
1863
1864
1865
  			if (cifs_parse_security_flavors(string, vol) != 0)
  				goto cifs_parse_mount_err;
  			break;
15b6a4732   Jeff Layton   cifs: add a cache...
1866
1867
1868
1869
1870
1871
1872
1873
  		case Opt_cache:
  			string = match_strdup(args);
  			if (string == NULL)
  				goto out_nomem;
  
  			if (cifs_parse_cache_flavor(string, vol) != 0)
  				goto cifs_parse_mount_err;
  			break;
8830d7e07   Sachin Prabhu   cifs: use standar...
1874
  		default:
d81625587   Jeff Layton   cifs: handle "slo...
1875
1876
1877
1878
1879
1880
  			/*
  			 * An option we don't recognize. Save it off for later
  			 * if we haven't already found one
  			 */
  			if (!invalid)
  				invalid = data;
8830d7e07   Sachin Prabhu   cifs: use standar...
1881
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1882
  		}
8830d7e07   Sachin Prabhu   cifs: use standar...
1883
1884
1885
  		/* Free up any allocated string */
  		kfree(string);
  		string = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1886
  	}
0eb8a132c   Jeff Layton   cifs: add "multiu...
1887

d81625587   Jeff Layton   cifs: handle "slo...
1888
  	if (!sloppy && invalid) {
0b456f04b   Andy Shevchenko   cifs: convert pri...
1889
1890
  		pr_err("CIFS: Unknown mount option \"%s\"
  ", invalid);
d81625587   Jeff Layton   cifs: handle "slo...
1891
1892
  		goto cifs_parse_mount_err;
  	}
8a8798a5f   Jeff Layton   cifs: fetch crede...
1893
1894
1895
  #ifndef CONFIG_KEYS
  	/* Muliuser mounts require CONFIG_KEYS support */
  	if (vol->multiuser) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1896
1897
  		cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1898
  		goto cifs_parse_mount_err;
0eb8a132c   Jeff Layton   cifs: add "multiu...
1899
  	}
8a8798a5f   Jeff Layton   cifs: fetch crede...
1900
  #endif
e5e69abd0   Jeff Layton   cifs: make error ...
1901
  	if (!vol->UNC) {
37d4f99b5   Jeff Layton   cifs: fix error h...
1902
1903
  		cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!
  ");
e5e69abd0   Jeff Layton   cifs: make error ...
1904
1905
  		goto cifs_parse_mount_err;
  	}
0eb8a132c   Jeff Layton   cifs: add "multiu...
1906

62a1a439e   Jeff Layton   cifs: clean up ha...
1907
1908
  	/* make sure UNC has a share name */
  	if (!strchr(vol->UNC + 3, '\\')) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
1909
1910
  		cifs_dbg(VFS, "Malformed UNC. Unable to find share name.
  ");
62a1a439e   Jeff Layton   cifs: clean up ha...
1911
1912
  		goto cifs_parse_mount_err;
  	}
b979aaa17   Jeff Layton   cifs: get rid of ...
1913
1914
1915
1916
  	if (!got_ip) {
  		/* No ip= option specified? Try to get it from UNC */
  		if (!cifs_convert_address(dstaddr, &vol->UNC[2],
  						strlen(&vol->UNC[2]))) {
0b456f04b   Andy Shevchenko   cifs: convert pri...
1917
1918
  			pr_err("Unable to determine destination address.
  ");
b979aaa17   Jeff Layton   cifs: get rid of ...
1919
1920
1921
1922
1923
1924
  			goto cifs_parse_mount_err;
  		}
  	}
  
  	/* set the port that we got earlier */
  	cifs_set_port(dstaddr, port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1925

9b9d6b243   Jeff Layton   cifs: reinstate o...
1926
1927
1928
  	if (uid_specified)
  		vol->override_uid = override_uid;
  	else if (override_uid == 1)
0b456f04b   Andy Shevchenko   cifs: convert pri...
1929
1930
  		pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.
  ");
9b9d6b243   Jeff Layton   cifs: reinstate o...
1931
1932
1933
1934
  
  	if (gid_specified)
  		vol->override_gid = override_gid;
  	else if (override_gid == 1)
0b456f04b   Andy Shevchenko   cifs: convert pri...
1935
1936
  		pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.
  ");
9b9d6b243   Jeff Layton   cifs: reinstate o...
1937

b946845a9   Sean Finney   cifs: cifs_parse_...
1938
  	kfree(mountdata_copy);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1939
  	return 0;
b946845a9   Sean Finney   cifs: cifs_parse_...
1940

8830d7e07   Sachin Prabhu   cifs: use standar...
1941
  out_nomem:
0b456f04b   Andy Shevchenko   cifs: convert pri...
1942
1943
  	pr_warn("Could not allocate temporary buffer
  ");
b946845a9   Sean Finney   cifs: cifs_parse_...
1944
  cifs_parse_mount_err:
8830d7e07   Sachin Prabhu   cifs: use standar...
1945
  	kfree(string);
b946845a9   Sean Finney   cifs: cifs_parse_...
1946
1947
  	kfree(mountdata_copy);
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1948
  }
3eb9a8893   Ben Greear   cifs: Allow bindi...
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
  /** Returns true if srcaddr isn't specified and rhs isn't
   * specified, or if srcaddr is specified and
   * matches the IP address of the rhs argument.
   */
  static bool
  srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
  {
  	switch (srcaddr->sa_family) {
  	case AF_UNSPEC:
  		return (rhs->sa_family == AF_UNSPEC);
  	case AF_INET: {
  		struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
  		struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
  		return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
  	}
  	case AF_INET6: {
  		struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
e3e2775ce   Nickolai Zeldovich   cifs: fix srcip_m...
1966
  		struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
3eb9a8893   Ben Greear   cifs: Allow bindi...
1967
1968
1969
1970
1971
1972
1973
  		return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
  	}
  	default:
  		WARN_ON(1);
  		return false; /* don't expect to be here */
  	}
  }
4b886136d   Pavel Shilovsky   CIFS: Add match_p...
1974
1975
1976
1977
1978
1979
1980
1981
  /*
   * If no port is specified in addr structure, we try to match with 445 port
   * and if it fails - with 139 ports. It should be called only if address
   * families of server and addr are equal.
   */
  static bool
  match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
  {
6da979106   Steve French   Elminate sparse _...
1982
  	__be16 port, *sport;
4b886136d   Pavel Shilovsky   CIFS: Add match_p...
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
  
  	switch (addr->sa_family) {
  	case AF_INET:
  		sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
  		port = ((struct sockaddr_in *) addr)->sin_port;
  		break;
  	case AF_INET6:
  		sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
  		port = ((struct sockaddr_in6 *) addr)->sin6_port;
  		break;
  	default:
  		WARN_ON(1);
  		return false;
  	}
  
  	if (!port) {
  		port = htons(CIFS_PORT);
  		if (port == *sport)
  			return true;
  
  		port = htons(RFC1001_PORT);
  	}
  
  	return port == *sport;
  }
3eb9a8893   Ben Greear   cifs: Allow bindi...
2008

4515148ef   Jeff Layton   cifs: move addres...
2009
  static bool
3eb9a8893   Ben Greear   cifs: Allow bindi...
2010
2011
  match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
  	      struct sockaddr *srcaddr)
4515148ef   Jeff Layton   cifs: move addres...
2012
  {
4515148ef   Jeff Layton   cifs: move addres...
2013
  	switch (addr->sa_family) {
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2014
2015
2016
2017
2018
2019
  	case AF_INET: {
  		struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
  		struct sockaddr_in *srv_addr4 =
  					(struct sockaddr_in *)&server->dstaddr;
  
  		if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
4515148ef   Jeff Layton   cifs: move addres...
2020
  			return false;
4515148ef   Jeff Layton   cifs: move addres...
2021
  		break;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2022
2023
2024
2025
2026
  	}
  	case AF_INET6: {
  		struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
  		struct sockaddr_in6 *srv_addr6 =
  					(struct sockaddr_in6 *)&server->dstaddr;
4515148ef   Jeff Layton   cifs: move addres...
2027
  		if (!ipv6_addr_equal(&addr6->sin6_addr,
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2028
  				     &srv_addr6->sin6_addr))
4515148ef   Jeff Layton   cifs: move addres...
2029
  			return false;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2030
  		if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
4515148ef   Jeff Layton   cifs: move addres...
2031
  			return false;
4515148ef   Jeff Layton   cifs: move addres...
2032
2033
  		break;
  	}
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2034
2035
2036
2037
  	default:
  		WARN_ON(1);
  		return false; /* don't expect to be here */
  	}
4515148ef   Jeff Layton   cifs: move addres...
2038

3eb9a8893   Ben Greear   cifs: Allow bindi...
2039
2040
  	if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
  		return false;
4515148ef   Jeff Layton   cifs: move addres...
2041
2042
  	return true;
  }
daf5b0b6f   Jeff Layton   cifs: match secTy...
2043
2044
2045
  static bool
  match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
  {
3f618223d   Jeff Layton   move sectype to t...
2046
2047
2048
2049
2050
2051
  	/*
  	 * The select_sectype function should either return the vol->sectype
  	 * that was specified, or "Unspecified" if that sectype was not
  	 * compatible with the given NEGOTIATE request.
  	 */
  	if (select_sectype(server, vol->sectype) == Unspecified)
daf5b0b6f   Jeff Layton   cifs: match secTy...
2052
  		return false;
daf5b0b6f   Jeff Layton   cifs: match secTy...
2053

3f618223d   Jeff Layton   move sectype to t...
2054
2055
2056
2057
2058
  	/*
  	 * Now check if signing mode is acceptable. No need to check
  	 * global_secflags at this point since if MUST_SIGN is set then
  	 * the server->sign had better be too.
  	 */
38d77c50b   Jeff Layton   cifs: track the e...
2059
2060
  	if (vol->sign && !server->sign)
  		return false;
daf5b0b6f   Jeff Layton   cifs: match secTy...
2061
2062
2063
  
  	return true;
  }
9fa114f74   Jeff Layton   cifs: remove unne...
2064
  static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
2065
  {
9fa114f74   Jeff Layton   cifs: remove unne...
2066
  	struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
a0b3df5cf   Jeff Layton   cifs: add a "nosh...
2067
2068
  	if (vol->nosharesock)
  		return 0;
23db65f51   Jeff Layton   cifs: add a smb_v...
2069
2070
  	if ((server->vals != vol->vals) || (server->ops != vol->ops))
  		return 0;
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
  	if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
  		return 0;
  
  	if (!match_address(server, addr,
  			   (struct sockaddr *)&vol->srcaddr))
  		return 0;
  
  	if (!match_port(server, addr))
  		return 0;
  
  	if (!match_security(server, vol))
  		return 0;
b782fcc1c   Rabin Vincent   cifs: unbreak TCP...
2083
  	if (server->echo_interval != vol->echo_interval * HZ)
adfeb3e00   Steve French   cifs: Make echo i...
2084
  		return 0;
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
2085
2086
  	return 1;
  }
e7ddee903   Jeff Layton   cifs: disable sha...
2087
  static struct TCP_Server_Info *
9fa114f74   Jeff Layton   cifs: remove unne...
2088
  cifs_find_tcp_session(struct smb_vol *vol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2089
  {
e7ddee903   Jeff Layton   cifs: disable sha...
2090
  	struct TCP_Server_Info *server;
e7ddee903   Jeff Layton   cifs: disable sha...
2091

3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2092
  	spin_lock(&cifs_tcp_ses_lock);
4515148ef   Jeff Layton   cifs: move addres...
2093
  	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
9fa114f74   Jeff Layton   cifs: remove unne...
2094
  		if (!match_server(server, vol))
daf5b0b6f   Jeff Layton   cifs: match secTy...
2095
  			continue;
e7ddee903   Jeff Layton   cifs: disable sha...
2096
  		++server->srv_count;
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2097
  		spin_unlock(&cifs_tcp_ses_lock);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2098
2099
  		cifs_dbg(FYI, "Existing tcp session with server found
  ");
e7ddee903   Jeff Layton   cifs: disable sha...
2100
  		return server;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2101
  	}
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2102
  	spin_unlock(&cifs_tcp_ses_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2103
2104
  	return NULL;
  }
1b20d6721   Cyrill Gorcunov   [CIFS] cifs_find_...
2105

48f9526f4   Pavel Shilovsky   CIFS: Fix a possi...
2106
2107
  void
  cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2108
  {
a5c3e1c72   Steve French   Revert "cifs: No ...
2109
  	struct task_struct *task;
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2110
  	spin_lock(&cifs_tcp_ses_lock);
e7ddee903   Jeff Layton   cifs: disable sha...
2111
  	if (--server->srv_count > 0) {
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2112
  		spin_unlock(&cifs_tcp_ses_lock);
e7ddee903   Jeff Layton   cifs: disable sha...
2113
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2114
  	}
1b20d6721   Cyrill Gorcunov   [CIFS] cifs_find_...
2115

f1d0c9986   Rob Landley   Make CIFS mount w...
2116
  	put_net(cifs_net_ns(server));
e7ddee903   Jeff Layton   cifs: disable sha...
2117
  	list_del_init(&server->tcp_ses_list);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2118
  	spin_unlock(&cifs_tcp_ses_lock);
dea570e08   Steve French   [CIFS] Remove ove...
2119

c74093b69   Jeff Layton   cifs: set up recu...
2120
  	cancel_delayed_work_sync(&server->echo);
48f9526f4   Pavel Shilovsky   CIFS: Fix a possi...
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
  #ifdef CONFIG_CIFS_SMB2
  	if (from_reconnect)
  		/*
  		 * Avoid deadlock here: reconnect work calls
  		 * cifs_put_tcp_session() at its end. Need to be sure
  		 * that reconnect work does nothing with server pointer after
  		 * that step.
  		 */
  		cancel_delayed_work(&server->reconnect);
  	else
  		cancel_delayed_work_sync(&server->reconnect);
  #endif
e7ddee903   Jeff Layton   cifs: disable sha...
2133
2134
2135
  	spin_lock(&GlobalMid_Lock);
  	server->tcpStatus = CifsExiting;
  	spin_unlock(&GlobalMid_Lock);
dea570e08   Steve French   [CIFS] Remove ove...
2136

d2b915210   Shirish Pargaonkar   NTLM auth and sig...
2137
  	cifs_crypto_shash_release(server);
488f1d2d6   Suresh Jayaraman   cifs: define serv...
2138
  	cifs_fscache_release_client_cookie(server);
21e733930   Shirish Pargaonkar   NTLM auth and sig...
2139
2140
2141
  	kfree(server->session_key.response);
  	server->session_key.response = NULL;
  	server->session_key.len = 0;
a5c3e1c72   Steve French   Revert "cifs: No ...
2142
2143
2144
2145
  
  	task = xchg(&server->tsk, NULL);
  	if (task)
  		force_sig(SIGKILL, task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2146
  }
63c038c29   Jeff Layton   cifs: move alloca...
2147
2148
2149
2150
  static struct TCP_Server_Info *
  cifs_get_tcp_session(struct smb_vol *volume_info)
  {
  	struct TCP_Server_Info *tcp_ses = NULL;
63c038c29   Jeff Layton   cifs: move alloca...
2151
  	int rc;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2152
2153
  	cifs_dbg(FYI, "UNC: %s
  ", volume_info->UNC);
63c038c29   Jeff Layton   cifs: move alloca...
2154
2155
  
  	/* see if we already have a matching tcp_ses */
9fa114f74   Jeff Layton   cifs: remove unne...
2156
  	tcp_ses = cifs_find_tcp_session(volume_info);
63c038c29   Jeff Layton   cifs: move alloca...
2157
2158
2159
2160
2161
2162
2163
2164
  	if (tcp_ses)
  		return tcp_ses;
  
  	tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
  	if (!tcp_ses) {
  		rc = -ENOMEM;
  		goto out_err;
  	}
23db65f51   Jeff Layton   cifs: add a smb_v...
2165
2166
  	tcp_ses->ops = volume_info->ops;
  	tcp_ses->vals = volume_info->vals;
f1d0c9986   Rob Landley   Make CIFS mount w...
2167
  	cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
63c038c29   Jeff Layton   cifs: move alloca...
2168
2169
2170
  	tcp_ses->hostname = extract_hostname(volume_info->UNC);
  	if (IS_ERR(tcp_ses->hostname)) {
  		rc = PTR_ERR(tcp_ses->hostname);
f7c5445a9   Shirish Pargaonkar   NTLM auth and sig...
2171
  		goto out_err_crypto_release;
63c038c29   Jeff Layton   cifs: move alloca...
2172
2173
2174
2175
  	}
  
  	tcp_ses->noblocksnd = volume_info->noblocksnd;
  	tcp_ses->noautotune = volume_info->noautotune;
6a5fa2362   Steve French   [CIFS] Add suppor...
2176
  	tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
fc40f9cf8   Pavel Shilovsky   CIFS: Simplify in...
2177
  	tcp_ses->in_flight = 0;
2d86dbc97   Pavel Shilovsky   CIFS: Introduce c...
2178
  	tcp_ses->credits = 1;
63c038c29   Jeff Layton   cifs: move alloca...
2179
2180
2181
2182
2183
2184
2185
2186
  	init_waitqueue_head(&tcp_ses->response_q);
  	init_waitqueue_head(&tcp_ses->request_q);
  	INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
  	mutex_init(&tcp_ses->srv_mutex);
  	memcpy(tcp_ses->workstation_RFC1001_name,
  		volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
  	memcpy(tcp_ses->server_RFC1001_name,
  		volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
5d0d28824   Shirish Pargaonkar   NTLM authenticati...
2187
  	tcp_ses->session_estab = false;
63c038c29   Jeff Layton   cifs: move alloca...
2188
  	tcp_ses->sequence_number = 0;
fda359436   Steve French   [CIFS] cifs: reco...
2189
  	tcp_ses->lstrp = jiffies;
58fa015f6   Jeff Layton   cifs: add missing...
2190
  	spin_lock_init(&tcp_ses->req_lock);
63c038c29   Jeff Layton   cifs: move alloca...
2191
2192
  	INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
  	INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
c74093b69   Jeff Layton   cifs: set up recu...
2193
  	INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
48f9526f4   Pavel Shilovsky   CIFS: Fix a possi...
2194
2195
2196
2197
  #ifdef CONFIG_CIFS_SMB2
  	INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
  	mutex_init(&tcp_ses->reconnect_mutex);
  #endif
9fa114f74   Jeff Layton   cifs: remove unne...
2198
2199
2200
2201
  	memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
  	       sizeof(tcp_ses->srcaddr));
  	memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
  		sizeof(tcp_ses->dstaddr));
39552ea81   Sachin Prabhu   cifs: Set client ...
2202
  #ifdef CONFIG_CIFS_SMB2
fa70b87cc   Steve French   SMB3: GUIDs shoul...
2203
  	generate_random_uuid(tcp_ses->client_guid);
39552ea81   Sachin Prabhu   cifs: Set client ...
2204
  #endif
63c038c29   Jeff Layton   cifs: move alloca...
2205
2206
2207
2208
2209
2210
2211
  	/*
  	 * at this point we are the only ones with the pointer
  	 * to the struct since the kernel thread not created yet
  	 * no need to spinlock this init of tcpStatus or srv_count
  	 */
  	tcp_ses->tcpStatus = CifsNew;
  	++tcp_ses->srv_count;
adfeb3e00   Steve French   cifs: Make echo i...
2212
2213
2214
2215
2216
  	if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
  		volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
  		tcp_ses->echo_interval = volume_info->echo_interval * HZ;
  	else
  		tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2217
  	rc = ip_connect(tcp_ses);
63c038c29   Jeff Layton   cifs: move alloca...
2218
  	if (rc < 0) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2219
2220
  		cifs_dbg(VFS, "Error connecting to socket. Aborting operation.
  ");
f7c5445a9   Shirish Pargaonkar   NTLM auth and sig...
2221
  		goto out_err_crypto_release;
63c038c29   Jeff Layton   cifs: move alloca...
2222
2223
2224
2225
2226
2227
2228
  	}
  
  	/*
  	 * since we're in a cifs function already, we know that
  	 * this will succeed. No need for try_module_get().
  	 */
  	__module_get(THIS_MODULE);
7c97c200e   Al Viro   cifs: fix the typ...
2229
  	tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
63c038c29   Jeff Layton   cifs: move alloca...
2230
2231
2232
  				  tcp_ses, "cifsd");
  	if (IS_ERR(tcp_ses->tsk)) {
  		rc = PTR_ERR(tcp_ses->tsk);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2233
2234
  		cifs_dbg(VFS, "error %d create cifsd thread
  ", rc);
63c038c29   Jeff Layton   cifs: move alloca...
2235
  		module_put(THIS_MODULE);
f7c5445a9   Shirish Pargaonkar   NTLM auth and sig...
2236
  		goto out_err_crypto_release;
63c038c29   Jeff Layton   cifs: move alloca...
2237
  	}
fd88ce931   Steve French   [CIFS] cifs: clar...
2238
  	tcp_ses->tcpStatus = CifsNeedNegotiate;
63c038c29   Jeff Layton   cifs: move alloca...
2239
2240
  
  	/* thread spawned, put it on the list */
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2241
  	spin_lock(&cifs_tcp_ses_lock);
63c038c29   Jeff Layton   cifs: move alloca...
2242
  	list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2243
  	spin_unlock(&cifs_tcp_ses_lock);
63c038c29   Jeff Layton   cifs: move alloca...
2244

488f1d2d6   Suresh Jayaraman   cifs: define serv...
2245
  	cifs_fscache_get_client_cookie(tcp_ses);
c74093b69   Jeff Layton   cifs: set up recu...
2246
  	/* queue echo request delayed work */
adfeb3e00   Steve French   cifs: Make echo i...
2247
  	queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
c74093b69   Jeff Layton   cifs: set up recu...
2248

63c038c29   Jeff Layton   cifs: move alloca...
2249
  	return tcp_ses;
f7c5445a9   Shirish Pargaonkar   NTLM auth and sig...
2250
  out_err_crypto_release:
d2b915210   Shirish Pargaonkar   NTLM auth and sig...
2251
  	cifs_crypto_shash_release(tcp_ses);
f1d0c9986   Rob Landley   Make CIFS mount w...
2252
  	put_net(cifs_net_ns(tcp_ses));
63c038c29   Jeff Layton   cifs: move alloca...
2253
2254
  out_err:
  	if (tcp_ses) {
8347a5cdd   Steve French   [CIFS] Fixing to ...
2255
2256
  		if (!IS_ERR(tcp_ses->hostname))
  			kfree(tcp_ses->hostname);
63c038c29   Jeff Layton   cifs: move alloca...
2257
2258
2259
2260
2261
2262
  		if (tcp_ses->ssocket)
  			sock_release(tcp_ses->ssocket);
  		kfree(tcp_ses);
  	}
  	return ERR_PTR(rc);
  }
96daf2b09   Steve French   [CIFS] Rename thr...
2263
  static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
2264
  {
3f618223d   Jeff Layton   move sectype to t...
2265
2266
2267
2268
2269
  	if (vol->sectype != Unspecified &&
  	    vol->sectype != ses->sectype)
  		return 0;
  
  	switch (ses->sectype) {
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
2270
  	case Kerberos:
64ed39dd1   Eric W. Biederman   cifs: Convert str...
2271
  		if (!uid_eq(vol->cred_uid, ses->cred_uid))
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
2272
2273
2274
  			return 0;
  		break;
  	default:
04febabcf   Jeff Layton   cifs: sanitize us...
2275
2276
2277
2278
2279
2280
  		/* NULL username means anonymous session */
  		if (ses->user_name == NULL) {
  			if (!vol->nullauth)
  				return 0;
  			break;
  		}
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
2281
  		/* anything else takes username/password */
04febabcf   Jeff Layton   cifs: sanitize us...
2282
2283
  		if (strncmp(ses->user_name,
  			    vol->username ? vol->username : "",
8c3a2b4c4   Scott Lovenberg   cifs: Move string...
2284
  			    CIFS_MAX_USERNAME_LEN))
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
2285
  			return 0;
08b37d518   Jeff Layton   cifs: ensure that...
2286
  		if ((vol->username && strlen(vol->username) != 0) &&
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
2287
2288
2289
  		    ses->password != NULL &&
  		    strncmp(ses->password,
  			    vol->password ? vol->password : "",
8c3a2b4c4   Scott Lovenberg   cifs: Move string...
2290
  			    CIFS_MAX_PASSWORD_LEN))
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
2291
2292
2293
2294
  			return 0;
  	}
  	return 1;
  }
96daf2b09   Steve French   [CIFS] Rename thr...
2295
  static struct cifs_ses *
4ff67b720   Jeff Layton   cifs: clean up ci...
2296
  cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2297
  {
96daf2b09   Steve French   [CIFS] Rename thr...
2298
  	struct cifs_ses *ses;
dea570e08   Steve French   [CIFS] Remove ove...
2299

3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2300
  	spin_lock(&cifs_tcp_ses_lock);
4ff67b720   Jeff Layton   cifs: clean up ci...
2301
  	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
7f48558e6   Shirish Pargaonkar   cifs: Send a logo...
2302
2303
  		if (ses->status == CifsExiting)
  			continue;
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
2304
2305
  		if (!match_session(ses, vol))
  			continue;
14fbf50d6   Jeff Layton   cifs: reinstate s...
2306
  		++ses->ses_count;
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2307
  		spin_unlock(&cifs_tcp_ses_lock);
14fbf50d6   Jeff Layton   cifs: reinstate s...
2308
2309
  		return ses;
  	}
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2310
  	spin_unlock(&cifs_tcp_ses_lock);
14fbf50d6   Jeff Layton   cifs: reinstate s...
2311
2312
  	return NULL;
  }
dea570e08   Steve French   [CIFS] Remove ove...
2313

14fbf50d6   Jeff Layton   cifs: reinstate s...
2314
  static void
96daf2b09   Steve French   [CIFS] Rename thr...
2315
  cifs_put_smb_ses(struct cifs_ses *ses)
14fbf50d6   Jeff Layton   cifs: reinstate s...
2316
  {
7f48558e6   Shirish Pargaonkar   cifs: Send a logo...
2317
  	unsigned int rc, xid;
14fbf50d6   Jeff Layton   cifs: reinstate s...
2318
  	struct TCP_Server_Info *server = ses->server;
dea570e08   Steve French   [CIFS] Remove ove...
2319

f96637be0   Joe Perches   [CIFS] cifs: Rena...
2320
2321
  	cifs_dbg(FYI, "%s: ses_count=%d
  ", __func__, ses->ses_count);
7f48558e6   Shirish Pargaonkar   cifs: Send a logo...
2322

3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2323
  	spin_lock(&cifs_tcp_ses_lock);
7f48558e6   Shirish Pargaonkar   cifs: Send a logo...
2324
2325
2326
2327
  	if (ses->status == CifsExiting) {
  		spin_unlock(&cifs_tcp_ses_lock);
  		return;
  	}
14fbf50d6   Jeff Layton   cifs: reinstate s...
2328
  	if (--ses->ses_count > 0) {
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2329
  		spin_unlock(&cifs_tcp_ses_lock);
14fbf50d6   Jeff Layton   cifs: reinstate s...
2330
2331
  		return;
  	}
7f48558e6   Shirish Pargaonkar   cifs: Send a logo...
2332
2333
  	if (ses->status == CifsGood)
  		ses->status = CifsExiting;
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2334
  	spin_unlock(&cifs_tcp_ses_lock);
dea570e08   Steve French   [CIFS] Remove ove...
2335

7f48558e6   Shirish Pargaonkar   cifs: Send a logo...
2336
  	if (ses->status == CifsExiting && server->ops->logoff) {
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2337
  		xid = get_xid();
7f48558e6   Shirish Pargaonkar   cifs: Send a logo...
2338
2339
2340
2341
2342
  		rc = server->ops->logoff(xid, ses);
  		if (rc)
  			cifs_dbg(VFS, "%s: Session Logoff failure rc=%d
  ",
  				__func__, rc);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2343
  		_free_xid(xid);
14fbf50d6   Jeff Layton   cifs: reinstate s...
2344
  	}
7f48558e6   Shirish Pargaonkar   cifs: Send a logo...
2345
2346
2347
2348
  
  	spin_lock(&cifs_tcp_ses_lock);
  	list_del_init(&ses->smb_ses_list);
  	spin_unlock(&cifs_tcp_ses_lock);
14fbf50d6   Jeff Layton   cifs: reinstate s...
2349
  	sesInfoFree(ses);
48f9526f4   Pavel Shilovsky   CIFS: Fix a possi...
2350
  	cifs_put_tcp_session(server, 0);
14fbf50d6   Jeff Layton   cifs: reinstate s...
2351
  }
dea570e08   Steve French   [CIFS] Remove ove...
2352

8a8798a5f   Jeff Layton   cifs: fetch crede...
2353
  #ifdef CONFIG_KEYS
057d6332b   Chen Gang   cifs: extend the ...
2354
2355
  /* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
  #define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
8a8798a5f   Jeff Layton   cifs: fetch crede...
2356
2357
2358
2359
2360
2361
  
  /* Populate username and pw fields from keyring if possible */
  static int
  cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
  {
  	int rc = 0;
146aa8b14   David Howells   KEYS: Merge the t...
2362
2363
  	const char *delim, *payload;
  	char *desc;
8a8798a5f   Jeff Layton   cifs: fetch crede...
2364
2365
2366
2367
2368
  	ssize_t len;
  	struct key *key;
  	struct TCP_Server_Info *server = ses->server;
  	struct sockaddr_in *sa;
  	struct sockaddr_in6 *sa6;
146aa8b14   David Howells   KEYS: Merge the t...
2369
  	const struct user_key_payload *upayload;
8a8798a5f   Jeff Layton   cifs: fetch crede...
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
  
  	desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
  	if (!desc)
  		return -ENOMEM;
  
  	/* try to find an address key first */
  	switch (server->dstaddr.ss_family) {
  	case AF_INET:
  		sa = (struct sockaddr_in *)&server->dstaddr;
  		sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
  		break;
  	case AF_INET6:
  		sa6 = (struct sockaddr_in6 *)&server->dstaddr;
  		sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
  		break;
  	default:
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2386
2387
2388
  		cifs_dbg(FYI, "Bad ss_family (%hu)
  ",
  			 server->dstaddr.ss_family);
8a8798a5f   Jeff Layton   cifs: fetch crede...
2389
2390
2391
  		rc = -EINVAL;
  		goto out_err;
  	}
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2392
2393
  	cifs_dbg(FYI, "%s: desc=%s
  ", __func__, desc);
8a8798a5f   Jeff Layton   cifs: fetch crede...
2394
2395
2396
  	key = request_key(&key_type_logon, desc, "");
  	if (IS_ERR(key)) {
  		if (!ses->domainName) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2397
2398
  			cifs_dbg(FYI, "domainName is NULL
  ");
8a8798a5f   Jeff Layton   cifs: fetch crede...
2399
2400
2401
2402
2403
2404
  			rc = PTR_ERR(key);
  			goto out_err;
  		}
  
  		/* didn't work, try to find a domain key */
  		sprintf(desc, "cifs:d:%s", ses->domainName);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2405
2406
  		cifs_dbg(FYI, "%s: desc=%s
  ", __func__, desc);
8a8798a5f   Jeff Layton   cifs: fetch crede...
2407
2408
2409
2410
2411
2412
2413
2414
  		key = request_key(&key_type_logon, desc, "");
  		if (IS_ERR(key)) {
  			rc = PTR_ERR(key);
  			goto out_err;
  		}
  	}
  
  	down_read(&key->sem);
146aa8b14   David Howells   KEYS: Merge the t...
2415
  	upayload = user_key_payload(key);
8a8798a5f   Jeff Layton   cifs: fetch crede...
2416
  	if (IS_ERR_OR_NULL(upayload)) {
4edc53c1f   Jeff Layton   cifs: fix error h...
2417
  		rc = upayload ? PTR_ERR(upayload) : -EINVAL;
8a8798a5f   Jeff Layton   cifs: fetch crede...
2418
2419
2420
2421
  		goto out_key_put;
  	}
  
  	/* find first : in payload */
146aa8b14   David Howells   KEYS: Merge the t...
2422
  	payload = upayload->data;
8a8798a5f   Jeff Layton   cifs: fetch crede...
2423
  	delim = strnchr(payload, upayload->datalen, ':');
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2424
2425
  	cifs_dbg(FYI, "payload=%s
  ", payload);
8a8798a5f   Jeff Layton   cifs: fetch crede...
2426
  	if (!delim) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2427
2428
2429
  		cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)
  ",
  			 upayload->datalen);
8a8798a5f   Jeff Layton   cifs: fetch crede...
2430
2431
2432
2433
2434
  		rc = -EINVAL;
  		goto out_key_put;
  	}
  
  	len = delim - payload;
8c3a2b4c4   Scott Lovenberg   cifs: Move string...
2435
  	if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2436
2437
2438
  		cifs_dbg(FYI, "Bad value from username search (len=%zd)
  ",
  			 len);
8a8798a5f   Jeff Layton   cifs: fetch crede...
2439
2440
2441
2442
2443
2444
  		rc = -EINVAL;
  		goto out_key_put;
  	}
  
  	vol->username = kstrndup(payload, len, GFP_KERNEL);
  	if (!vol->username) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2445
2446
2447
  		cifs_dbg(FYI, "Unable to allocate %zd bytes for username
  ",
  			 len);
8a8798a5f   Jeff Layton   cifs: fetch crede...
2448
2449
2450
  		rc = -ENOMEM;
  		goto out_key_put;
  	}
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2451
2452
  	cifs_dbg(FYI, "%s: username=%s
  ", __func__, vol->username);
8a8798a5f   Jeff Layton   cifs: fetch crede...
2453
2454
  
  	len = key->datalen - (len + 1);
8c3a2b4c4   Scott Lovenberg   cifs: Move string...
2455
  	if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2456
2457
  		cifs_dbg(FYI, "Bad len for password search (len=%zd)
  ", len);
8a8798a5f   Jeff Layton   cifs: fetch crede...
2458
2459
2460
2461
2462
2463
2464
2465
2466
  		rc = -EINVAL;
  		kfree(vol->username);
  		vol->username = NULL;
  		goto out_key_put;
  	}
  
  	++delim;
  	vol->password = kstrndup(delim, len, GFP_KERNEL);
  	if (!vol->password) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2467
2468
2469
  		cifs_dbg(FYI, "Unable to allocate %zd bytes for password
  ",
  			 len);
8a8798a5f   Jeff Layton   cifs: fetch crede...
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
  		rc = -ENOMEM;
  		kfree(vol->username);
  		vol->username = NULL;
  		goto out_key_put;
  	}
  
  out_key_put:
  	up_read(&key->sem);
  	key_put(key);
  out_err:
  	kfree(desc);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2481
2482
  	cifs_dbg(FYI, "%s: returning %d
  ", __func__, rc);
8a8798a5f   Jeff Layton   cifs: fetch crede...
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
  	return rc;
  }
  #else /* ! CONFIG_KEYS */
  static inline int
  cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
  		   struct cifs_ses *ses __attribute__((unused)))
  {
  	return -ENOSYS;
  }
  #endif /* CONFIG_KEYS */
96daf2b09   Steve French   [CIFS] Rename thr...
2493
  static struct cifs_ses *
36988c76f   Jeff Layton   cifs: move SMB se...
2494
2495
  cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
  {
286170aa2   Pavel Shilovsky   CIFS: Move protoc...
2496
2497
  	int rc = -ENOMEM;
  	unsigned int xid;
96daf2b09   Steve French   [CIFS] Rename thr...
2498
  	struct cifs_ses *ses;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2499
2500
  	struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
  	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
36988c76f   Jeff Layton   cifs: move SMB se...
2501

6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2502
  	xid = get_xid();
36988c76f   Jeff Layton   cifs: move SMB se...
2503

4ff67b720   Jeff Layton   cifs: clean up ci...
2504
  	ses = cifs_find_smb_ses(server, volume_info);
36988c76f   Jeff Layton   cifs: move SMB se...
2505
  	if (ses) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2506
2507
2508
  		cifs_dbg(FYI, "Existing smb sess found (status=%d)
  ",
  			 ses->status);
36988c76f   Jeff Layton   cifs: move SMB se...
2509

36988c76f   Jeff Layton   cifs: move SMB se...
2510
  		mutex_lock(&ses->session_mutex);
198b56827   Jeff Layton   cifs: break negot...
2511
2512
2513
2514
2515
  		rc = cifs_negotiate_protocol(xid, ses);
  		if (rc) {
  			mutex_unlock(&ses->session_mutex);
  			/* problem -- put our ses reference */
  			cifs_put_smb_ses(ses);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2516
  			free_xid(xid);
198b56827   Jeff Layton   cifs: break negot...
2517
2518
  			return ERR_PTR(rc);
  		}
36988c76f   Jeff Layton   cifs: move SMB se...
2519
  		if (ses->need_reconnect) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2520
2521
  			cifs_dbg(FYI, "Session needs reconnect
  ");
36988c76f   Jeff Layton   cifs: move SMB se...
2522
2523
2524
2525
2526
2527
  			rc = cifs_setup_session(xid, ses,
  						volume_info->local_nls);
  			if (rc) {
  				mutex_unlock(&ses->session_mutex);
  				/* problem -- put our reference */
  				cifs_put_smb_ses(ses);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2528
  				free_xid(xid);
36988c76f   Jeff Layton   cifs: move SMB se...
2529
2530
2531
2532
  				return ERR_PTR(rc);
  			}
  		}
  		mutex_unlock(&ses->session_mutex);
460cf3411   Jeff Layton   cifs: fix potenti...
2533
2534
  
  		/* existing SMB ses has a server reference already */
48f9526f4   Pavel Shilovsky   CIFS: Fix a possi...
2535
  		cifs_put_tcp_session(server, 0);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2536
  		free_xid(xid);
36988c76f   Jeff Layton   cifs: move SMB se...
2537
2538
  		return ses;
  	}
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2539
2540
  	cifs_dbg(FYI, "Existing smb sess not found
  ");
36988c76f   Jeff Layton   cifs: move SMB se...
2541
2542
2543
2544
2545
2546
  	ses = sesInfoAlloc();
  	if (ses == NULL)
  		goto get_ses_fail;
  
  	/* new SMB session uses our server ref */
  	ses->server = server;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2547
2548
  	if (server->dstaddr.ss_family == AF_INET6)
  		sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
36988c76f   Jeff Layton   cifs: move SMB se...
2549
  	else
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2550
  		sprintf(ses->serverName, "%pI4", &addr->sin_addr);
36988c76f   Jeff Layton   cifs: move SMB se...
2551

8727c8a85   Steve French   Allow user names ...
2552
2553
2554
2555
2556
  	if (volume_info->username) {
  		ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
  		if (!ses->user_name)
  			goto get_ses_fail;
  	}
36988c76f   Jeff Layton   cifs: move SMB se...
2557
2558
2559
2560
2561
2562
2563
2564
  
  	/* volume_info->password freed at unmount */
  	if (volume_info->password) {
  		ses->password = kstrdup(volume_info->password, GFP_KERNEL);
  		if (!ses->password)
  			goto get_ses_fail;
  	}
  	if (volume_info->domainname) {
d3686d54c   Shirish Pargaonkar   cifs: Cleanup and...
2565
2566
2567
  		ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
  		if (!ses->domainName)
  			goto get_ses_fail;
36988c76f   Jeff Layton   cifs: move SMB se...
2568
  	}
3e4b3e1f6   Jeff Layton   cifs: add separat...
2569
  	ses->cred_uid = volume_info->cred_uid;
36988c76f   Jeff Layton   cifs: move SMB se...
2570
  	ses->linux_uid = volume_info->linux_uid;
d9b942013   Steve French   [CIFS] Warn on re...
2571

28e11bd86   Jeff Layton   cifs: add new fie...
2572
2573
  	ses->sectype = volume_info->sectype;
  	ses->sign = volume_info->sign;
36988c76f   Jeff Layton   cifs: move SMB se...
2574
2575
  
  	mutex_lock(&ses->session_mutex);
198b56827   Jeff Layton   cifs: break negot...
2576
2577
2578
  	rc = cifs_negotiate_protocol(xid, ses);
  	if (!rc)
  		rc = cifs_setup_session(xid, ses, volume_info->local_nls);
36988c76f   Jeff Layton   cifs: move SMB se...
2579
  	mutex_unlock(&ses->session_mutex);
c8e56f1f4   Steve French   Revert "[CIFS] Fi...
2580
  	if (rc)
36988c76f   Jeff Layton   cifs: move SMB se...
2581
2582
2583
  		goto get_ses_fail;
  
  	/* success, put it on the list */
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2584
  	spin_lock(&cifs_tcp_ses_lock);
36988c76f   Jeff Layton   cifs: move SMB se...
2585
  	list_add(&ses->smb_ses_list, &server->smb_ses_list);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2586
  	spin_unlock(&cifs_tcp_ses_lock);
36988c76f   Jeff Layton   cifs: move SMB se...
2587

6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2588
  	free_xid(xid);
36988c76f   Jeff Layton   cifs: move SMB se...
2589
2590
2591
2592
  	return ses;
  
  get_ses_fail:
  	sesInfoFree(ses);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2593
  	free_xid(xid);
36988c76f   Jeff Layton   cifs: move SMB se...
2594
2595
  	return ERR_PTR(rc);
  }
96daf2b09   Steve French   [CIFS] Rename thr...
2596
  static int match_tcon(struct cifs_tcon *tcon, const char *unc)
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
2597
2598
2599
2600
2601
2602
2603
  {
  	if (tcon->tidStatus == CifsExiting)
  		return 0;
  	if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
  		return 0;
  	return 1;
  }
96daf2b09   Steve French   [CIFS] Rename thr...
2604
2605
  static struct cifs_tcon *
  cifs_find_tcon(struct cifs_ses *ses, const char *unc)
f1987b44f   Jeff Layton   cifs: reinstate s...
2606
2607
  {
  	struct list_head *tmp;
96daf2b09   Steve French   [CIFS] Rename thr...
2608
  	struct cifs_tcon *tcon;
f1987b44f   Jeff Layton   cifs: reinstate s...
2609

3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2610
  	spin_lock(&cifs_tcp_ses_lock);
f1987b44f   Jeff Layton   cifs: reinstate s...
2611
  	list_for_each(tmp, &ses->tcon_list) {
96daf2b09   Steve French   [CIFS] Rename thr...
2612
  		tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
37bb04e5a   Pavel Shilovsky   CIFS: Simplify co...
2613
  		if (!match_tcon(tcon, unc))
f1987b44f   Jeff Layton   cifs: reinstate s...
2614
  			continue;
f1987b44f   Jeff Layton   cifs: reinstate s...
2615
  		++tcon->tc_count;
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2616
  		spin_unlock(&cifs_tcp_ses_lock);
dea570e08   Steve French   [CIFS] Remove ove...
2617
  		return tcon;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2618
  	}
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2619
  	spin_unlock(&cifs_tcp_ses_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2620
2621
  	return NULL;
  }
48f9526f4   Pavel Shilovsky   CIFS: Fix a possi...
2622
  void
96daf2b09   Steve French   [CIFS] Rename thr...
2623
  cifs_put_tcon(struct cifs_tcon *tcon)
f1987b44f   Jeff Layton   cifs: reinstate s...
2624
  {
2e6e02ab6   Pavel Shilovsky   CIFS: Move protoc...
2625
  	unsigned int xid;
96daf2b09   Steve French   [CIFS] Rename thr...
2626
  	struct cifs_ses *ses = tcon->ses;
f1987b44f   Jeff Layton   cifs: reinstate s...
2627

f96637be0   Joe Perches   [CIFS] cifs: Rena...
2628
2629
  	cifs_dbg(FYI, "%s: tc_count=%d
  ", __func__, tcon->tc_count);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2630
  	spin_lock(&cifs_tcp_ses_lock);
f1987b44f   Jeff Layton   cifs: reinstate s...
2631
  	if (--tcon->tc_count > 0) {
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2632
  		spin_unlock(&cifs_tcp_ses_lock);
f1987b44f   Jeff Layton   cifs: reinstate s...
2633
2634
2635
2636
  		return;
  	}
  
  	list_del_init(&tcon->tcon_list);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2637
  	spin_unlock(&cifs_tcp_ses_lock);
f1987b44f   Jeff Layton   cifs: reinstate s...
2638

6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2639
  	xid = get_xid();
2e6e02ab6   Pavel Shilovsky   CIFS: Move protoc...
2640
2641
  	if (ses->server->ops->tree_disconnect)
  		ses->server->ops->tree_disconnect(xid, tcon);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2642
  	_free_xid(xid);
f1987b44f   Jeff Layton   cifs: reinstate s...
2643

d03382ce9   Suresh Jayaraman   cifs: define supe...
2644
  	cifs_fscache_release_super_cookie(tcon);
9f841593f   Steve French   [CIFS] relinquish...
2645
  	tconInfoFree(tcon);
f1987b44f   Jeff Layton   cifs: reinstate s...
2646
2647
  	cifs_put_smb_ses(ses);
  }
96daf2b09   Steve French   [CIFS] Rename thr...
2648
2649
  static struct cifs_tcon *
  cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
d00c28de5   Jeff Layton   cifs: move tcon f...
2650
2651
  {
  	int rc, xid;
96daf2b09   Steve French   [CIFS] Rename thr...
2652
  	struct cifs_tcon *tcon;
d00c28de5   Jeff Layton   cifs: move tcon f...
2653
2654
2655
  
  	tcon = cifs_find_tcon(ses, volume_info->UNC);
  	if (tcon) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2656
2657
  		cifs_dbg(FYI, "Found match on UNC path
  ");
d00c28de5   Jeff Layton   cifs: move tcon f...
2658
2659
2660
  		/* existing tcon already has a reference */
  		cifs_put_smb_ses(ses);
  		if (tcon->seal != volume_info->seal)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2661
2662
  			cifs_dbg(VFS, "transport encryption setting conflicts with existing tid
  ");
d00c28de5   Jeff Layton   cifs: move tcon f...
2663
2664
  		return tcon;
  	}
2e6e02ab6   Pavel Shilovsky   CIFS: Move protoc...
2665
2666
2667
2668
  	if (!ses->server->ops->tree_connect) {
  		rc = -ENOSYS;
  		goto out_fail;
  	}
d00c28de5   Jeff Layton   cifs: move tcon f...
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
  	tcon = tconInfoAlloc();
  	if (tcon == NULL) {
  		rc = -ENOMEM;
  		goto out_fail;
  	}
  
  	tcon->ses = ses;
  	if (volume_info->password) {
  		tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
  		if (!tcon->password) {
  			rc = -ENOMEM;
  			goto out_fail;
  		}
  	}
2e6e02ab6   Pavel Shilovsky   CIFS: Move protoc...
2683
2684
2685
2686
  	/*
  	 * BB Do we need to wrap session_mutex around this TCon call and Unix
  	 * SetFS as we do on SessSetup and reconnect?
  	 */
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2687
  	xid = get_xid();
2e6e02ab6   Pavel Shilovsky   CIFS: Move protoc...
2688
2689
  	rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
  					    volume_info->local_nls);
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
2690
  	free_xid(xid);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2691
2692
  	cifs_dbg(FYI, "Tcon rc = %d
  ", rc);
d00c28de5   Jeff Layton   cifs: move tcon f...
2693
2694
2695
2696
2697
  	if (rc)
  		goto out_fail;
  
  	if (volume_info->nodfs) {
  		tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2698
2699
  		cifs_dbg(FYI, "DFS disabled (%d)
  ", tcon->Flags);
d00c28de5   Jeff Layton   cifs: move tcon f...
2700
2701
  	}
  	tcon->seal = volume_info->seal;
b618f001a   Steve French   [SMB3] Enable che...
2702
2703
2704
2705
2706
2707
2708
2709
2710
  	tcon->use_persistent = false;
  	/* check if SMB2 or later, CIFS does not support persistent handles */
  	if (volume_info->persistent) {
  		if (ses->server->vals->protocol_id == 0) {
  			cifs_dbg(VFS,
  			     "SMB3 or later required for persistent handles
  ");
  			rc = -EOPNOTSUPP;
  			goto out_fail;
592fafe64   Steve French   Add resilienthand...
2711
  #ifdef CONFIG_CIFS_SMB2
b618f001a   Steve French   [SMB3] Enable che...
2712
2713
2714
2715
2716
2717
2718
2719
2720
  		} else if (ses->server->capabilities &
  			   SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
  			tcon->use_persistent = true;
  		else /* persistent handles requested but not supported */ {
  			cifs_dbg(VFS,
  				"Persistent handles not supported on share
  ");
  			rc = -EOPNOTSUPP;
  			goto out_fail;
592fafe64   Steve French   Add resilienthand...
2721
  #endif /* CONFIG_CIFS_SMB2 */
b618f001a   Steve French   [SMB3] Enable che...
2722
  		}
592fafe64   Steve French   Add resilienthand...
2723
  #ifdef CONFIG_CIFS_SMB2
b618f001a   Steve French   [SMB3] Enable che...
2724
2725
2726
2727
2728
2729
  	} else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
  	     && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
  	     && (volume_info->nopersistent == false)) {
  		cifs_dbg(FYI, "enabling persistent handles
  ");
  		tcon->use_persistent = true;
592fafe64   Steve French   Add resilienthand...
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
  #endif /* CONFIG_CIFS_SMB2 */
  	} else if (volume_info->resilient) {
  		if (ses->server->vals->protocol_id == 0) {
  			cifs_dbg(VFS,
  			     "SMB2.1 or later required for resilient handles
  ");
  			rc = -EOPNOTSUPP;
  			goto out_fail;
  		}
  		tcon->use_resilient = true;
b618f001a   Steve French   [SMB3] Enable che...
2740
  	}
2e6e02ab6   Pavel Shilovsky   CIFS: Move protoc...
2741
2742
2743
2744
2745
  	/*
  	 * We can have only one retry value for a connection to a share so for
  	 * resources mounted more than once to the same server share the last
  	 * value passed in for the retry flag is used.
  	 */
d00c28de5   Jeff Layton   cifs: move tcon f...
2746
2747
2748
  	tcon->retry = volume_info->retry;
  	tcon->nocase = volume_info->nocase;
  	tcon->local_lease = volume_info->local_lease;
233839b1d   Pavel Shilovsky   CIFS: Fix fast le...
2749
  	INIT_LIST_HEAD(&tcon->pending_opens);
d00c28de5   Jeff Layton   cifs: move tcon f...
2750

3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2751
  	spin_lock(&cifs_tcp_ses_lock);
d00c28de5   Jeff Layton   cifs: move tcon f...
2752
  	list_add(&tcon->tcon_list, &ses->tcon_list);
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
2753
  	spin_unlock(&cifs_tcp_ses_lock);
d00c28de5   Jeff Layton   cifs: move tcon f...
2754

d03382ce9   Suresh Jayaraman   cifs: define supe...
2755
  	cifs_fscache_get_super_cookie(tcon);
d00c28de5   Jeff Layton   cifs: move tcon f...
2756
2757
2758
2759
2760
2761
  	return tcon;
  
  out_fail:
  	tconInfoFree(tcon);
  	return ERR_PTR(rc);
  }
9d002df49   Jeff Layton   cifs: add routine...
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
  void
  cifs_put_tlink(struct tcon_link *tlink)
  {
  	if (!tlink || IS_ERR(tlink))
  		return;
  
  	if (!atomic_dec_and_test(&tlink->tl_count) ||
  	    test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
  		tlink->tl_time = jiffies;
  		return;
  	}
  
  	if (!IS_ERR(tlink_tcon(tlink)))
  		cifs_put_tcon(tlink_tcon(tlink));
  	kfree(tlink);
  	return;
  }
d00c28de5   Jeff Layton   cifs: move tcon f...
2779

25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2780
  static inline struct tcon_link *
cd51875d5   Pavel Shilovsky   CIFS: Fix sparse ...
2781
2782
2783
2784
  cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
  {
  	return cifs_sb->master_tlink;
  }
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
  
  static int
  compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
  {
  	struct cifs_sb_info *old = CIFS_SB(sb);
  	struct cifs_sb_info *new = mnt_data->cifs_sb;
  
  	if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
  		return 0;
  
  	if ((old->mnt_cifs_flags & CIFS_MOUNT_MASK) !=
  	    (new->mnt_cifs_flags & CIFS_MOUNT_MASK))
  		return 0;
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2798
  	/*
5eba8ab36   Jeff Layton   cifs: allow for l...
2799
2800
  	 * We want to share sb only if we don't specify an r/wsize or
  	 * specified r/wsize is greater than or equal to existing one.
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2801
2802
2803
  	 */
  	if (new->wsize && new->wsize < old->wsize)
  		return 0;
5eba8ab36   Jeff Layton   cifs: allow for l...
2804
2805
  	if (new->rsize && new->rsize < old->rsize)
  		return 0;
1f68233c5   Eric W. Biederman   cifs: Convert str...
2806
  	if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
  		return 0;
  
  	if (old->mnt_file_mode != new->mnt_file_mode ||
  	    old->mnt_dir_mode != new->mnt_dir_mode)
  		return 0;
  
  	if (strcmp(old->local_nls->charset, new->local_nls->charset))
  		return 0;
  
  	if (old->actimeo != new->actimeo)
  		return 0;
  
  	return 1;
  }
c1d8b24d1   Sachin Prabhu   Compare prepaths ...
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
  static int
  match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
  {
  	struct cifs_sb_info *old = CIFS_SB(sb);
  	struct cifs_sb_info *new = mnt_data->cifs_sb;
  
  	if (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) {
  		if (!(new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH))
  			return 0;
  		/* The prepath should be null terminated strings */
  		if (strcmp(new->prepath, old->prepath))
  			return 0;
  
  		return 1;
  	}
  	return 0;
  }
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2838
2839
2840
2841
2842
2843
2844
  int
  cifs_match_super(struct super_block *sb, void *data)
  {
  	struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
  	struct smb_vol *volume_info;
  	struct cifs_sb_info *cifs_sb;
  	struct TCP_Server_Info *tcp_srv;
96daf2b09   Steve French   [CIFS] Rename thr...
2845
2846
  	struct cifs_ses *ses;
  	struct cifs_tcon *tcon;
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2847
  	struct tcon_link *tlink;
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2848
  	int rc = 0;
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
  	spin_lock(&cifs_tcp_ses_lock);
  	cifs_sb = CIFS_SB(sb);
  	tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
  	if (IS_ERR(tlink)) {
  		spin_unlock(&cifs_tcp_ses_lock);
  		return rc;
  	}
  	tcon = tlink_tcon(tlink);
  	ses = tcon->ses;
  	tcp_srv = ses->server;
  
  	volume_info = mnt_data->vol;
9fa114f74   Jeff Layton   cifs: remove unne...
2861
  	if (!match_server(tcp_srv, volume_info) ||
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2862
  	    !match_session(ses, volume_info) ||
c1d8b24d1   Sachin Prabhu   Compare prepaths ...
2863
2864
  	    !match_tcon(tcon, volume_info->UNC) ||
  	    !match_prepath(sb, mnt_data)) {
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2865
2866
2867
2868
2869
2870
  		rc = 0;
  		goto out;
  	}
  
  	rc = compare_mount_options(sb, mnt_data);
  out:
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2871
  	spin_unlock(&cifs_tcp_ses_lock);
f484b5d00   Jeff Layton   cifs: drop spinlo...
2872
  	cifs_put_tlink(tlink);
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
2873
2874
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2875
  int
b669f33ca   Pavel Shilovsky   CIFS: Move gettin...
2876
  get_dfs_path(const unsigned int xid, struct cifs_ses *ses, const char *old_path,
2e6e02ab6   Pavel Shilovsky   CIFS: Move protoc...
2877
2878
  	     const struct nls_table *nls_codepage, unsigned int *num_referrals,
  	     struct dfs_info3_param **referrals, int remap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2879
2880
2881
  {
  	char *temp_unc;
  	int rc = 0;
b669f33ca   Pavel Shilovsky   CIFS: Move gettin...
2882
  	if (!ses->server->ops->tree_connect || !ses->server->ops->get_dfs_refer)
2e6e02ab6   Pavel Shilovsky   CIFS: Move protoc...
2883
2884
2885
2886
  		return -ENOSYS;
  
  	*num_referrals = 0;
  	*referrals = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2887

2e6e02ab6   Pavel Shilovsky   CIFS: Move protoc...
2888
  	if (ses->ipc_tid == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2889
  		temp_unc = kmalloc(2 /* for slashes */ +
2e6e02ab6   Pavel Shilovsky   CIFS: Move protoc...
2890
2891
  			strnlen(ses->serverName, SERVER_NAME_LEN_WITH_NULL * 2)
  				+ 1 + 4 /* slash IPC$ */ + 2, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2892
2893
2894
2895
  		if (temp_unc == NULL)
  			return -ENOMEM;
  		temp_unc[0] = '\\';
  		temp_unc[1] = '\\';
2e6e02ab6   Pavel Shilovsky   CIFS: Move protoc...
2896
2897
2898
2899
  		strcpy(temp_unc + 2, ses->serverName);
  		strcpy(temp_unc + 2 + strlen(ses->serverName), "\\IPC$");
  		rc = ses->server->ops->tree_connect(xid, ses, temp_unc, NULL,
  						    nls_codepage);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2900
2901
  		cifs_dbg(FYI, "Tcon rc = %d ipc_tid = %d
  ", rc, ses->ipc_tid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2902
2903
2904
  		kfree(temp_unc);
  	}
  	if (rc == 0)
b669f33ca   Pavel Shilovsky   CIFS: Move gettin...
2905
2906
2907
  		rc = ses->server->ops->get_dfs_refer(xid, ses, old_path,
  						     referrals, num_referrals,
  						     nls_codepage, remap);
2e6e02ab6   Pavel Shilovsky   CIFS: Move protoc...
2908
2909
  	/*
  	 * BB - map targetUNCs to dfs_info3 structures, here or in
b669f33ca   Pavel Shilovsky   CIFS: Move gettin...
2910
  	 * ses->server->ops->get_dfs_refer.
2e6e02ab6   Pavel Shilovsky   CIFS: Move protoc...
2911
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2912
2913
2914
  
  	return rc;
  }
09e50d55a   Jeff Layton   lockdep: annotate...
2915
2916
2917
2918
2919
2920
2921
2922
  #ifdef CONFIG_DEBUG_LOCK_ALLOC
  static struct lock_class_key cifs_key[2];
  static struct lock_class_key cifs_slock_key[2];
  
  static inline void
  cifs_reclassify_socket4(struct socket *sock)
  {
  	struct sock *sk = sock->sk;
fafc4e1ea   Hannes Frederic Sowa   sock: tigthen loc...
2923
  	BUG_ON(!sock_allow_reclassification(sk));
09e50d55a   Jeff Layton   lockdep: annotate...
2924
2925
2926
2927
2928
2929
2930
2931
  	sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
  		&cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
  }
  
  static inline void
  cifs_reclassify_socket6(struct socket *sock)
  {
  	struct sock *sk = sock->sk;
fafc4e1ea   Hannes Frederic Sowa   sock: tigthen loc...
2932
  	BUG_ON(!sock_allow_reclassification(sk));
09e50d55a   Jeff Layton   lockdep: annotate...
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
  	sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
  		&cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
  }
  #else
  static inline void
  cifs_reclassify_socket4(struct socket *sock)
  {
  }
  
  static inline void
  cifs_reclassify_socket6(struct socket *sock)
  {
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2947
  /* See RFC1001 section 14 on representation of Netbios names */
50c2f7538   Steve French   [CIFS] whitespace...
2948
  static void rfc1002mangle(char *target, char *source, unsigned int length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2949
  {
50c2f7538   Steve French   [CIFS] whitespace...
2950
  	unsigned int i, j;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2951

50c2f7538   Steve French   [CIFS] whitespace...
2952
  	for (i = 0, j = 0; i < (length); i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2953
2954
2955
  		/* mask a nibble at a time and encode */
  		target[j] = 'A' + (0x0F & (source[i] >> 4));
  		target[j+1] = 'A' + (0x0F & source[i]);
50c2f7538   Steve French   [CIFS] whitespace...
2956
  		j += 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2957
2958
2959
  	}
  
  }
3eb9a8893   Ben Greear   cifs: Allow bindi...
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
  static int
  bind_socket(struct TCP_Server_Info *server)
  {
  	int rc = 0;
  	if (server->srcaddr.ss_family != AF_UNSPEC) {
  		/* Bind to the specified local IP address */
  		struct socket *socket = server->ssocket;
  		rc = socket->ops->bind(socket,
  				       (struct sockaddr *) &server->srcaddr,
  				       sizeof(server->srcaddr));
  		if (rc < 0) {
  			struct sockaddr_in *saddr4;
  			struct sockaddr_in6 *saddr6;
  			saddr4 = (struct sockaddr_in *)&server->srcaddr;
  			saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
  			if (saddr6->sin6_family == AF_INET6)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2976
2977
2978
  				cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d
  ",
  					 &saddr6->sin6_addr, rc);
3eb9a8893   Ben Greear   cifs: Allow bindi...
2979
  			else
f96637be0   Joe Perches   [CIFS] cifs: Rena...
2980
2981
2982
  				cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d
  ",
  					 &saddr4->sin_addr.s_addr, rc);
3eb9a8893   Ben Greear   cifs: Allow bindi...
2983
2984
2985
2986
  		}
  	}
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2987
2988
  
  static int
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2989
  ip_rfc1001_connect(struct TCP_Server_Info *server)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2990
2991
  {
  	int rc = 0;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
  	/*
  	 * some servers require RFC1001 sessinit before sending
  	 * negprot - BB check reconnection in case where second
  	 * sessinit is sent but no second negprot
  	 */
  	struct rfc1002_session_packet *ses_init_buf;
  	struct smb_hdr *smb_buf;
  	ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
  			       GFP_KERNEL);
  	if (ses_init_buf) {
  		ses_init_buf->trailer.session_req.called_len = 32;
997152f62   Colin Ian King   cifs: remove redu...
3003
  		if (server->server_RFC1001_name[0] != 0)
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
  			rfc1002mangle(ses_init_buf->trailer.
  				      session_req.called_name,
  				      server->server_RFC1001_name,
  				      RFC1001_NAME_LEN_WITH_NULL);
  		else
  			rfc1002mangle(ses_init_buf->trailer.
  				      session_req.called_name,
  				      DEFAULT_CIFS_CALLED_NAME,
  				      RFC1001_NAME_LEN_WITH_NULL);
  
  		ses_init_buf->trailer.session_req.calling_len = 32;
  
  		/*
  		 * calling name ends in null (byte 16) from old smb
  		 * convention.
  		 */
c85c35f8f   Steve French   Fix warning on im...
3020
  		if (server->workstation_RFC1001_name[0] != 0)
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
  			rfc1002mangle(ses_init_buf->trailer.
  				      session_req.calling_name,
  				      server->workstation_RFC1001_name,
  				      RFC1001_NAME_LEN_WITH_NULL);
  		else
  			rfc1002mangle(ses_init_buf->trailer.
  				      session_req.calling_name,
  				      "LINUX_CIFS_CLNT",
  				      RFC1001_NAME_LEN_WITH_NULL);
  
  		ses_init_buf->trailer.session_req.scope1 = 0;
  		ses_init_buf->trailer.session_req.scope2 = 0;
  		smb_buf = (struct smb_hdr *)ses_init_buf;
  
  		/* sizeof RFC1002_SESSION_REQUEST with no scope */
be8e3b004   Steve French   consistently use ...
3036
  		smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
  		rc = smb_send(server, smb_buf, 0x44);
  		kfree(ses_init_buf);
  		/*
  		 * RFC1001 layer in at least one server
  		 * requires very short break before negprot
  		 * presumably because not expecting negprot
  		 * to follow so fast.  This is a simple
  		 * solution that works without
  		 * complicating the code and causes no
  		 * significant slowing down on mount
  		 * for everyone else
  		 */
  		usleep_range(1000, 2000);
  	}
  	/*
  	 * else the negprot may still work without this
  	 * even though malloc failed
  	 */
  
  	return rc;
  }
  
  static int
  generic_ip_connect(struct TCP_Server_Info *server)
  {
  	int rc = 0;
6da979106   Steve French   Elminate sparse _...
3063
  	__be16 sport;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3064
  	int slen, sfamily;
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
3065
  	struct socket *socket = server->ssocket;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
  	struct sockaddr *saddr;
  
  	saddr = (struct sockaddr *) &server->dstaddr;
  
  	if (server->dstaddr.ss_family == AF_INET6) {
  		sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
  		slen = sizeof(struct sockaddr_in6);
  		sfamily = AF_INET6;
  	} else {
  		sport = ((struct sockaddr_in *) saddr)->sin_port;
  		slen = sizeof(struct sockaddr_in);
  		sfamily = AF_INET;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3079

bcf4b1063   Jeff Layton   cifs: make ipv4_c...
3080
  	if (socket == NULL) {
f1d0c9986   Rob Landley   Make CIFS mount w...
3081
3082
  		rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
  				   IPPROTO_TCP, &socket, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3083
  		if (rc < 0) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3084
3085
  			cifs_dbg(VFS, "Error %d creating socket
  ", rc);
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3086
  			server->ssocket = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3087
  			return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3088
  		}
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
3089
3090
  
  		/* BB other socket options to set KEEPALIVE, NODELAY? */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3091
3092
  		cifs_dbg(FYI, "Socket created
  ");
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
3093
3094
  		server->ssocket = socket;
  		socket->sk->sk_allocation = GFP_NOFS;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3095
3096
3097
3098
  		if (sfamily == AF_INET6)
  			cifs_reclassify_socket6(socket);
  		else
  			cifs_reclassify_socket4(socket);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3099
  	}
3eb9a8893   Ben Greear   cifs: Allow bindi...
3100
3101
3102
  	rc = bind_socket(server);
  	if (rc < 0)
  		return rc;
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
3103
3104
  	/*
  	 * Eventually check for other socket options to change from
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3105
3106
  	 * the default. sock_setsockopt not used because it expects
  	 * user space buffer
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
3107
3108
  	 */
  	socket->sk->sk_rcvtimeo = 7 * HZ;
da505c386   Steve French   [CIFS] Make socke...
3109
  	socket->sk->sk_sndtimeo = 5 * HZ;
edf1ae403   Steve French   [CIFS] Reduce num...
3110

b387eaeb6   Steve French   [CIFS] Do not shr...
3111
  	/* make the bufsizes depend on wsize/rsize and max requests */
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
3112
3113
3114
3115
3116
  	if (server->noautotune) {
  		if (socket->sk->sk_sndbuf < (200 * 1024))
  			socket->sk->sk_sndbuf = 200 * 1024;
  		if (socket->sk->sk_rcvbuf < (140 * 1024))
  			socket->sk->sk_rcvbuf = 140 * 1024;
edf1ae403   Steve French   [CIFS] Reduce num...
3117
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3118

6a5fa2362   Steve French   [CIFS] Add suppor...
3119
  	if (server->tcp_nodelay) {
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3120
  		int val = 1;
6a5fa2362   Steve French   [CIFS] Add suppor...
3121
3122
3123
  		rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
  				(char *)&val, sizeof(val));
  		if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3124
3125
3126
  			cifs_dbg(FYI, "set TCP_NODELAY socket option error %d
  ",
  				 rc);
6a5fa2362   Steve French   [CIFS] Add suppor...
3127
  	}
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3128
3129
  	cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx
  ",
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
3130
  		 socket->sk->sk_sndbuf,
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3131
  		 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
bcf4b1063   Jeff Layton   cifs: make ipv4_c...
3132

ee1b3ea9e   Jeff Layton   cifs: set socket ...
3133
3134
  	rc = socket->ops->connect(socket, saddr, slen, 0);
  	if (rc < 0) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3135
3136
  		cifs_dbg(FYI, "Error %d connecting to server
  ", rc);
ee1b3ea9e   Jeff Layton   cifs: set socket ...
3137
3138
3139
3140
  		sock_release(socket);
  		server->ssocket = NULL;
  		return rc;
  	}
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3141
3142
  	if (sport == htons(RFC1001_PORT))
  		rc = ip_rfc1001_connect(server);
50c2f7538   Steve French   [CIFS] whitespace...
3143

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3144
3145
3146
3147
  	return rc;
  }
  
  static int
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3148
  ip_connect(struct TCP_Server_Info *server)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3149
  {
6da979106   Steve French   Elminate sparse _...
3150
  	__be16 *sport;
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3151
3152
  	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
  	struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3153

a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3154
3155
3156
3157
  	if (server->dstaddr.ss_family == AF_INET6)
  		sport = &addr6->sin6_port;
  	else
  		sport = &addr->sin_port;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3158

a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3159
3160
  	if (*sport == 0) {
  		int rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3161

a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3162
3163
  		/* try with 445 port at first */
  		*sport = htons(CIFS_PORT);
3eb9a8893   Ben Greear   cifs: Allow bindi...
3164

a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3165
  		rc = generic_ip_connect(server);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3166
  		if (rc >= 0)
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3167
  			return rc;
6a5fa2362   Steve French   [CIFS] Add suppor...
3168

a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3169
3170
  		/* if it failed, try with 139 port */
  		*sport = htons(RFC1001_PORT);
6a5fa2362   Steve French   [CIFS] Add suppor...
3171
  	}
a9f1b85e5   Pavel Shilovsky   CIFS: Simplify ip...
3172
  	return generic_ip_connect(server);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3173
  }
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
3174
  void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
2c6292ae4   Al Viro   cifs: don't pass ...
3175
  			  struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
8af189715   Steve French   [CIFS] on reconne...
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
  {
  	/* if we are reconnecting then should we check to see if
  	 * any requested capabilities changed locally e.g. via
  	 * remount but we can not do much about it here
  	 * if they have (even if we could detect it by the following)
  	 * Perhaps we could add a backpointer to array of sb from tcon
  	 * or if we change to make all sb to same share the same
  	 * sb as NFS - then we only have one backpointer to sb.
  	 * What if we wanted to mount the server share twice once with
  	 * and once without posixacls or posix paths? */
  	__u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
50c2f7538   Steve French   [CIFS] whitespace...
3187

c18c842b1   Steve French   [CIFS] Allow disa...
3188
3189
3190
  	if (vol_info && vol_info->no_linux_ext) {
  		tcon->fsUnixInfo.Capability = 0;
  		tcon->unix_ext = 0; /* Unix Extensions disabled */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3191
3192
  		cifs_dbg(FYI, "Linux protocol extensions disabled
  ");
c18c842b1   Steve French   [CIFS] Allow disa...
3193
3194
3195
3196
3197
  		return;
  	} else if (vol_info)
  		tcon->unix_ext = 1; /* Unix Extensions supported */
  
  	if (tcon->unix_ext == 0) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3198
3199
  		cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect
  ");
c18c842b1   Steve French   [CIFS] Allow disa...
3200
3201
  		return;
  	}
50c2f7538   Steve French   [CIFS] whitespace...
3202

fb8c4b14d   Steve French   [CIFS] whitespace...
3203
  	if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
8af189715   Steve French   [CIFS] on reconne...
3204
  		__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3205
3206
  		cifs_dbg(FYI, "unix caps which server supports %lld
  ", cap);
8af189715   Steve French   [CIFS] on reconne...
3207
3208
  		/* check for reconnect case in which we do not
  		   want to change the mount behavior if we can avoid it */
fb8c4b14d   Steve French   [CIFS] whitespace...
3209
  		if (vol_info == NULL) {
50c2f7538   Steve French   [CIFS] whitespace...
3210
  			/* turn off POSIX ACL and PATHNAMES if not set
8af189715   Steve French   [CIFS] on reconne...
3211
3212
3213
  			   originally at mount time */
  			if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
  				cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
11b6d6450   Igor Mammedov   [CIFS] Only conve...
3214
3215
  			if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
  				if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3216
3217
  					cifs_dbg(VFS, "POSIXPATH support change
  ");
8af189715   Steve French   [CIFS] on reconne...
3218
  				cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
11b6d6450   Igor Mammedov   [CIFS] Only conve...
3219
  			} else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3220
3221
3222
3223
  				cifs_dbg(VFS, "possible reconnect error
  ");
  				cifs_dbg(VFS, "server disabled POSIX path support
  ");
11b6d6450   Igor Mammedov   [CIFS] Only conve...
3224
  			}
8af189715   Steve French   [CIFS] on reconne...
3225
  		}
50c2f7538   Steve French   [CIFS] whitespace...
3226

6848b7334   Steve French   [CIFS] When manda...
3227
  		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3228
3229
  			cifs_dbg(VFS, "per-share encryption not supported yet
  ");
6848b7334   Steve French   [CIFS] When manda...
3230

8af189715   Steve French   [CIFS] on reconne...
3231
  		cap &= CIFS_UNIX_CAP_MASK;
75865f8cc   Steve French   [CIFS] Add in som...
3232
  		if (vol_info && vol_info->no_psx_acl)
8af189715   Steve French   [CIFS] on reconne...
3233
  			cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
75865f8cc   Steve French   [CIFS] Add in som...
3234
  		else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3235
3236
  			cifs_dbg(FYI, "negotiated posix acl support
  ");
2c6292ae4   Al Viro   cifs: don't pass ...
3237
3238
3239
  			if (cifs_sb)
  				cifs_sb->mnt_cifs_flags |=
  					CIFS_MOUNT_POSIXACL;
8af189715   Steve French   [CIFS] on reconne...
3240
  		}
75865f8cc   Steve French   [CIFS] Add in som...
3241
  		if (vol_info && vol_info->posix_paths == 0)
8af189715   Steve French   [CIFS] on reconne...
3242
  			cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
75865f8cc   Steve French   [CIFS] Add in som...
3243
  		else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3244
3245
  			cifs_dbg(FYI, "negotiate posix pathnames
  ");
2c6292ae4   Al Viro   cifs: don't pass ...
3246
3247
  			if (cifs_sb)
  				cifs_sb->mnt_cifs_flags |=
8af189715   Steve French   [CIFS] on reconne...
3248
3249
  					CIFS_MOUNT_POSIX_PATHS;
  		}
50c2f7538   Steve French   [CIFS] whitespace...
3250

f96637be0   Joe Perches   [CIFS] cifs: Rena...
3251
3252
  		cifs_dbg(FYI, "Negotiate caps 0x%x
  ", (int)cap);
8af189715   Steve French   [CIFS] on reconne...
3253
  #ifdef CONFIG_CIFS_DEBUG2
75865f8cc   Steve French   [CIFS] Add in som...
3254
  		if (cap & CIFS_UNIX_FCNTL_CAP)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3255
3256
  			cifs_dbg(FYI, "FCNTL cap
  ");
75865f8cc   Steve French   [CIFS] Add in som...
3257
  		if (cap & CIFS_UNIX_EXTATTR_CAP)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3258
3259
  			cifs_dbg(FYI, "EXTATTR cap
  ");
75865f8cc   Steve French   [CIFS] Add in som...
3260
  		if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3261
3262
  			cifs_dbg(FYI, "POSIX path cap
  ");
75865f8cc   Steve French   [CIFS] Add in som...
3263
  		if (cap & CIFS_UNIX_XATTR_CAP)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3264
3265
  			cifs_dbg(FYI, "XATTR cap
  ");
75865f8cc   Steve French   [CIFS] Add in som...
3266
  		if (cap & CIFS_UNIX_POSIX_ACL_CAP)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3267
3268
  			cifs_dbg(FYI, "POSIX ACL cap
  ");
75865f8cc   Steve French   [CIFS] Add in som...
3269
  		if (cap & CIFS_UNIX_LARGE_READ_CAP)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3270
3271
  			cifs_dbg(FYI, "very large read cap
  ");
75865f8cc   Steve French   [CIFS] Add in som...
3272
  		if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3273
3274
  			cifs_dbg(FYI, "very large write cap
  ");
6848b7334   Steve French   [CIFS] When manda...
3275
  		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3276
3277
  			cifs_dbg(FYI, "transport encryption cap
  ");
6848b7334   Steve French   [CIFS] When manda...
3278
  		if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3279
3280
  			cifs_dbg(FYI, "mandatory transport encryption cap
  ");
8af189715   Steve French   [CIFS] on reconne...
3281
3282
  #endif /* CIFS_DEBUG2 */
  		if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
442aa310f   Steve French   [CIFS] Support fo...
3283
  			if (vol_info == NULL) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3284
3285
  				cifs_dbg(FYI, "resetting capabilities failed
  ");
442aa310f   Steve French   [CIFS] Support fo...
3286
  			} else
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3287
3288
  				cifs_dbg(VFS, "Negotiating Unix capabilities with the server failed. Consider mounting with the Unix Extensions disabled if problems are found by specifying the nounix mount option.
  ");
5a44b3190   Steve French   [CIFS] Add warnin...
3289

8af189715   Steve French   [CIFS] on reconne...
3290
3291
3292
  		}
  	}
  }
4214ebf46   Sachin Prabhu   Fix memory leaks ...
3293
  int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3294
  			struct cifs_sb_info *cifs_sb)
b1c8d2b42   Jeff Layton   cifs: handle the ...
3295
  {
2de970ff6   Jeff Layton   cifs: implement r...
3296
  	INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
2ced6f693   Al Viro   cifs: initialize ...
3297
3298
  	spin_lock_init(&cifs_sb->tlink_tree_lock);
  	cifs_sb->tlink_tree = RB_ROOT;
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
3299
  	/*
5eba8ab36   Jeff Layton   cifs: allow for l...
3300
3301
  	 * Temporarily set r/wsize for matching superblock. If we end up using
  	 * new sb then client will later negotiate it downward if needed.
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
3302
  	 */
5eba8ab36   Jeff Layton   cifs: allow for l...
3303
  	cifs_sb->rsize = pvolume_info->rsize;
25c7f41e9   Pavel Shilovsky   CIFS: Migrate to ...
3304
  	cifs_sb->wsize = pvolume_info->wsize;
3b7952109   Steve French   [CIFS] Fix cifs r...
3305
3306
3307
3308
  	cifs_sb->mnt_uid = pvolume_info->linux_uid;
  	cifs_sb->mnt_gid = pvolume_info->linux_gid;
  	cifs_sb->mnt_file_mode = pvolume_info->file_mode;
  	cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3309
3310
3311
  	cifs_dbg(FYI, "file mode: 0x%hx  dir mode: 0x%hx
  ",
  		 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
3b7952109   Steve French   [CIFS] Fix cifs r...
3312

6d20e8406   Suresh Jayaraman   cifs: add attribu...
3313
  	cifs_sb->actimeo = pvolume_info->actimeo;
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3314
  	cifs_sb->local_nls = pvolume_info->local_nls;
6d20e8406   Suresh Jayaraman   cifs: add attribu...
3315

3b7952109   Steve French   [CIFS] Fix cifs r...
3316
3317
3318
3319
  	if (pvolume_info->noperm)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
  	if (pvolume_info->setuids)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
959326553   Steve French   CIFS: Add new mou...
3320
3321
  	if (pvolume_info->setuidfromacl)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
3b7952109   Steve French   [CIFS] Fix cifs r...
3322
3323
3324
  	if (pvolume_info->server_ino)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
  	if (pvolume_info->remap)
2baa26825   Steve French   Remap reserved po...
3325
3326
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
  	if (pvolume_info->sfu_remap)
3b7952109   Steve French   [CIFS] Fix cifs r...
3327
3328
3329
3330
3331
3332
3333
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
  	if (pvolume_info->no_xattr)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
  	if (pvolume_info->sfu_emul)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
  	if (pvolume_info->nobrl)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
be652445f   Steve French   [CIFS] Add new no...
3334
  	if (pvolume_info->nostrictsync)
4717bed68   Steve French   [CIFS] fix build ...
3335
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
13a6e42af   Steve French   [CIFS] add mount ...
3336
3337
  	if (pvolume_info->mand_lock)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
d4ffff1fa   Pavel Shilovsky   CIFS: Add rwpidfo...
3338
3339
  	if (pvolume_info->rwpidforward)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
3b7952109   Steve French   [CIFS] Fix cifs r...
3340
3341
  	if (pvolume_info->cifs_acl)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
3c7c87fd5   Sachin Prabhu   CIFS: Show backup...
3342
  	if (pvolume_info->backupuid_specified) {
3d3ea8e64   Shirish Pargaonkar   cifs: Add mount o...
3343
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
3c7c87fd5   Sachin Prabhu   CIFS: Show backup...
3344
3345
3346
  		cifs_sb->mnt_backupuid = pvolume_info->backupuid;
  	}
  	if (pvolume_info->backupgid_specified) {
3d3ea8e64   Shirish Pargaonkar   cifs: Add mount o...
3347
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
3c7c87fd5   Sachin Prabhu   CIFS: Show backup...
3348
3349
  		cifs_sb->mnt_backupgid = pvolume_info->backupgid;
  	}
3b7952109   Steve French   [CIFS] Fix cifs r...
3350
3351
3352
3353
3354
3355
  	if (pvolume_info->override_uid)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
  	if (pvolume_info->override_gid)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
  	if (pvolume_info->dynperm)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
fa1df75d4   Suresh Jayaraman   cifs: add mount o...
3356
3357
  	if (pvolume_info->fsc)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
0eb8a132c   Jeff Layton   cifs: add "multiu...
3358
3359
3360
  	if (pvolume_info->multiuser)
  		cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
  					    CIFS_MOUNT_NO_PERM);
d39454ffe   Pavel Shilovsky   CIFS: Add strictc...
3361
3362
  	if (pvolume_info->strict_io)
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
3b7952109   Steve French   [CIFS] Fix cifs r...
3363
  	if (pvolume_info->direct_io) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3364
3365
  		cifs_dbg(FYI, "mounting share using direct i/o
  ");
3b7952109   Steve French   [CIFS] Fix cifs r...
3366
3367
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
  	}
736a33205   Stefan Metzmacher   cifs: add "mfsyml...
3368
3369
  	if (pvolume_info->mfsymlinks) {
  		if (pvolume_info->sfu_emul) {
db8b631d4   Steve French   Allow mknod and m...
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
  			/*
  			 * Our SFU ("Services for Unix" emulation does not allow
  			 * creating symlinks but does allow reading existing SFU
  			 * symlinks (it does allow both creating and reading SFU
  			 * style mknod and FIFOs though). When "mfsymlinks" and
  			 * "sfu" are both enabled at the same time, it allows
  			 * reading both types of symlinks, but will only create
  			 * them with mfsymlinks format. This allows better
  			 * Apple compatibility (probably better for Samba too)
  			 * while still recognizing old Windows style symlinks.
  			 */
  			cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled
  ");
736a33205   Stefan Metzmacher   cifs: add "mfsyml...
3383
  		}
db8b631d4   Steve French   Allow mknod and m...
3384
  		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
736a33205   Stefan Metzmacher   cifs: add "mfsyml...
3385
  	}
3b7952109   Steve French   [CIFS] Fix cifs r...
3386
3387
  
  	if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3388
3389
  		cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported
  ");
4214ebf46   Sachin Prabhu   Fix memory leaks ...
3390
3391
3392
3393
3394
3395
3396
3397
  
  	if (pvolume_info->prepath) {
  		cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
  		if (cifs_sb->prepath == NULL)
  			return -ENOMEM;
  	}
  
  	return 0;
b1c8d2b42   Jeff Layton   cifs: handle the ...
3398
  }
b9bce2e9f   Jeff Layton   cifs: fix expand_...
3399
3400
  static void
  cleanup_volume_info_contents(struct smb_vol *volume_info)
1bfe73c25   Igor Mammedov   Remote DFS root s...
3401
  {
b946845a9   Sean Finney   cifs: cifs_parse_...
3402
  	kfree(volume_info->username);
1bfe73c25   Igor Mammedov   Remote DFS root s...
3403
  	kzfree(volume_info->password);
95c754545   Jesper Juhl   CIFS: Don't free ...
3404
  	kfree(volume_info->UNC);
b946845a9   Sean Finney   cifs: cifs_parse_...
3405
3406
  	kfree(volume_info->domainname);
  	kfree(volume_info->iocharset);
1bfe73c25   Igor Mammedov   Remote DFS root s...
3407
  	kfree(volume_info->prepath);
b9bce2e9f   Jeff Layton   cifs: fix expand_...
3408
3409
3410
3411
3412
3413
3414
3415
  }
  
  void
  cifs_cleanup_volume_info(struct smb_vol *volume_info)
  {
  	if (!volume_info)
  		return;
  	cleanup_volume_info_contents(volume_info);
1bfe73c25   Igor Mammedov   Remote DFS root s...
3416
  	kfree(volume_info);
1bfe73c25   Igor Mammedov   Remote DFS root s...
3417
  }
b9bce2e9f   Jeff Layton   cifs: fix expand_...
3418

2d6d589d8   Steve French   [CIFS] remove som...
3419
  #ifdef CONFIG_CIFS_DFS_UPCALL
6d3ea7e49   Steve French   CIFS: Make use of...
3420
3421
3422
3423
  /*
   * cifs_build_path_to_root returns full path to root when we do not have an
   * exiting connection (tcon)
   */
1bfe73c25   Igor Mammedov   Remote DFS root s...
3424
  static char *
b2a0fa152   Jeff Layton   cifs: fix build_u...
3425
  build_unc_path_to_root(const struct smb_vol *vol,
1bfe73c25   Igor Mammedov   Remote DFS root s...
3426
3427
  		const struct cifs_sb_info *cifs_sb)
  {
b2a0fa152   Jeff Layton   cifs: fix build_u...
3428
  	char *full_path, *pos;
839db3d10   Jeff Layton   cifs: fix up hand...
3429
  	unsigned int pplen = vol->prepath ? strlen(vol->prepath) + 1 : 0;
b2a0fa152   Jeff Layton   cifs: fix build_u...
3430
  	unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
1bfe73c25   Igor Mammedov   Remote DFS root s...
3431

b2a0fa152   Jeff Layton   cifs: fix build_u...
3432
  	full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
1bfe73c25   Igor Mammedov   Remote DFS root s...
3433
3434
  	if (full_path == NULL)
  		return ERR_PTR(-ENOMEM);
b2a0fa152   Jeff Layton   cifs: fix build_u...
3435
3436
3437
3438
  	strncpy(full_path, vol->UNC, unc_len);
  	pos = full_path + unc_len;
  
  	if (pplen) {
1fc29bace   Jeff Layton   cifs: fix off-by-...
3439
3440
  		*pos = CIFS_DIR_SEP(cifs_sb);
  		strncpy(pos + 1, vol->prepath, pplen);
b2a0fa152   Jeff Layton   cifs: fix build_u...
3441
3442
3443
3444
  		pos += pplen;
  	}
  
  	*pos = '\0'; /* add trailing null */
f87d39d95   Steve French   [CIFS] Migrate fr...
3445
  	convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3446
3447
  	cifs_dbg(FYI, "%s: full_path=%s
  ", __func__, full_path);
1bfe73c25   Igor Mammedov   Remote DFS root s...
3448
3449
  	return full_path;
  }
dd6139458   Sean Finney   cifs: Extract DFS...
3450
3451
3452
3453
  
  /*
   * Perform a dfs referral query for a share and (optionally) prefix
   *
046462abc   Sean Finney   cifs: Simplify ha...
3454
3455
3456
   * If a referral is found, cifs_sb->mountdata will be (re-)allocated
   * to a string containing updated options for the submount.  Otherwise it
   * will be left untouched.
dd6139458   Sean Finney   cifs: Extract DFS...
3457
3458
3459
3460
3461
   *
   * Returns the rc from get_dfs_path to the caller, which can be used to
   * determine whether there were referrals.
   */
  static int
b669f33ca   Pavel Shilovsky   CIFS: Move gettin...
3462
  expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
dd6139458   Sean Finney   cifs: Extract DFS...
3463
  		    struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
046462abc   Sean Finney   cifs: Simplify ha...
3464
  		    int check_prefix)
dd6139458   Sean Finney   cifs: Extract DFS...
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
  {
  	int rc;
  	unsigned int num_referrals = 0;
  	struct dfs_info3_param *referrals = NULL;
  	char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
  
  	full_path = build_unc_path_to_root(volume_info, cifs_sb);
  	if (IS_ERR(full_path))
  		return PTR_ERR(full_path);
  
  	/* For DFS paths, skip the first '\' of the UNC */
  	ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
b669f33ca   Pavel Shilovsky   CIFS: Move gettin...
3477
  	rc = get_dfs_path(xid, ses, ref_path, cifs_sb->local_nls,
2baa26825   Steve French   Remap reserved po...
3478
  			  &num_referrals, &referrals, cifs_remap(cifs_sb));
dd6139458   Sean Finney   cifs: Extract DFS...
3479
3480
3481
3482
3483
3484
3485
3486
3487
  
  	if (!rc && num_referrals > 0) {
  		char *fake_devname = NULL;
  
  		mdata = cifs_compose_mount_options(cifs_sb->mountdata,
  						   full_path + 1, referrals,
  						   &fake_devname);
  
  		free_dfs_info_array(referrals, num_referrals);
046462abc   Sean Finney   cifs: Simplify ha...
3488

dd6139458   Sean Finney   cifs: Extract DFS...
3489
3490
3491
  		if (IS_ERR(mdata)) {
  			rc = PTR_ERR(mdata);
  			mdata = NULL;
b9bce2e9f   Jeff Layton   cifs: fix expand_...
3492
3493
  		} else {
  			cleanup_volume_info_contents(volume_info);
b9bce2e9f   Jeff Layton   cifs: fix expand_...
3494
3495
  			rc = cifs_setup_volume_info(volume_info, mdata,
  							fake_devname);
dd6139458   Sean Finney   cifs: Extract DFS...
3496
  		}
b9bce2e9f   Jeff Layton   cifs: fix expand_...
3497
3498
  		kfree(fake_devname);
  		kfree(cifs_sb->mountdata);
046462abc   Sean Finney   cifs: Simplify ha...
3499
  		cifs_sb->mountdata = mdata;
dd6139458   Sean Finney   cifs: Extract DFS...
3500
3501
3502
3503
  	}
  	kfree(full_path);
  	return rc;
  }
2d6d589d8   Steve French   [CIFS] remove som...
3504
  #endif
1bfe73c25   Igor Mammedov   Remote DFS root s...
3505

04db79b01   Jeff Layton   cifs: factor smb_...
3506
3507
3508
  static int
  cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
  			const char *devname)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3509
  {
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3510
  	int rc = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3511

04db79b01   Jeff Layton   cifs: factor smb_...
3512
3513
  	if (cifs_parse_mount_options(mount_data, devname, volume_info))
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3514

7586b7658   Jeff Layton   cifs: don't decla...
3515
  	if (volume_info->nullauth) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3516
3517
  		cifs_dbg(FYI, "Anonymous login
  ");
04febabcf   Jeff Layton   cifs: sanitize us...
3518
3519
  		kfree(volume_info->username);
  		volume_info->username = NULL;
7586b7658   Jeff Layton   cifs: don't decla...
3520
  	} else if (volume_info->username) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3521
  		/* BB fixme parse for domain name here */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3522
3523
  		cifs_dbg(FYI, "Username: %s
  ", volume_info->username);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3524
  	} else {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3525
3526
  		cifs_dbg(VFS, "No username specified
  ");
50c2f7538   Steve French   [CIFS] whitespace...
3527
3528
  	/* In userspace mount helper we can get user name from alternate
  	   locations such as env variables and files on disk */
04db79b01   Jeff Layton   cifs: factor smb_...
3529
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3530
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3531
  	/* this is needed for ASCII cp to Unicode converts */
7586b7658   Jeff Layton   cifs: don't decla...
3532
  	if (volume_info->iocharset == NULL) {
a5fc4ce01   Jeff Layton   cifs: track local...
3533
3534
  		/* load_nls_default cannot return null */
  		volume_info->local_nls = load_nls_default();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3535
  	} else {
a5fc4ce01   Jeff Layton   cifs: track local...
3536
3537
  		volume_info->local_nls = load_nls(volume_info->iocharset);
  		if (volume_info->local_nls == NULL) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3538
3539
  			cifs_dbg(VFS, "CIFS mount error: iocharset %s not found
  ",
b6b38f704   Joe Perches   [CIFS] Neaten cER...
3540
  				 volume_info->iocharset);
04db79b01   Jeff Layton   cifs: factor smb_...
3541
  			return -ELIBACC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3542
3543
  		}
  	}
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3544

724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3545
3546
  	return rc;
  }
04db79b01   Jeff Layton   cifs: factor smb_...
3547
3548
3549
3550
3551
  struct smb_vol *
  cifs_get_volume_info(char *mount_data, const char *devname)
  {
  	int rc;
  	struct smb_vol *volume_info;
6ee9542a8   Jeff Layton   cifs: always zero...
3552
  	volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
04db79b01   Jeff Layton   cifs: factor smb_...
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
  	if (!volume_info)
  		return ERR_PTR(-ENOMEM);
  
  	rc = cifs_setup_volume_info(volume_info, mount_data, devname);
  	if (rc) {
  		cifs_cleanup_volume_info(volume_info);
  		volume_info = ERR_PTR(rc);
  	}
  
  	return volume_info;
  }
a6b5058fa   Aurelien Aptel   fs/cifs: make sha...
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
  static int
  cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
  					unsigned int xid,
  					struct cifs_tcon *tcon,
  					struct cifs_sb_info *cifs_sb,
  					char *full_path)
  {
  	int rc;
  	char *s;
  	char sep, tmp;
  
  	sep = CIFS_DIR_SEP(cifs_sb);
  	s = full_path;
  
  	rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
  	while (rc == 0) {
  		/* skip separators */
  		while (*s == sep)
  			s++;
  		if (!*s)
  			break;
  		/* next separator */
  		while (*s && *s != sep)
  			s++;
  
  		/*
  		 * temporarily null-terminate the path at the end of
  		 * the current component
  		 */
  		tmp = *s;
  		*s = 0;
  		rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
  						     full_path);
  		*s = tmp;
  	}
  	return rc;
  }
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3601
  int
2c6292ae4   Al Viro   cifs: don't pass ...
3602
  cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3603
  {
1daaae8fa   Jeff Layton   cifs: fix issue m...
3604
  	int rc;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
3605
  	unsigned int xid;
af4281dc2   Pavel Shilovsky   CIFS: Move inform...
3606
  	struct cifs_ses *ses;
96daf2b09   Steve French   [CIFS] Rename thr...
3607
  	struct cifs_tcon *tcon;
af4281dc2   Pavel Shilovsky   CIFS: Move inform...
3608
  	struct TCP_Server_Info *server;
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3609
3610
3611
3612
  	char   *full_path;
  	struct tcon_link *tlink;
  #ifdef CONFIG_CIFS_DFS_UPCALL
  	int referral_walks_count = 0;
20547490c   Jeff Layton   cifs: move bdi_se...
3613
  #endif
dd8544661   Al Viro   take bdi setup/de...
3614

b4caecd48   Christoph Hellwig   fs: introduce f_o...
3615
  	rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs");
dd8544661   Al Viro   take bdi setup/de...
3616
3617
  	if (rc)
  		return rc;
20547490c   Jeff Layton   cifs: move bdi_se...
3618
  #ifdef CONFIG_CIFS_DFS_UPCALL
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3619
3620
3621
3622
3623
  try_mount_again:
  	/* cleanup activities if we're chasing a referral */
  	if (referral_walks_count) {
  		if (tcon)
  			cifs_put_tcon(tcon);
af4281dc2   Pavel Shilovsky   CIFS: Move inform...
3624
3625
  		else if (ses)
  			cifs_put_smb_ses(ses);
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3626

1dfd18d05   Sachin Prabhu   cifs: Unset CIFS_...
3627
  		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
3628
  		free_xid(xid);
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3629
3630
  	}
  #endif
1daaae8fa   Jeff Layton   cifs: fix issue m...
3631
  	rc = 0;
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3632
  	tcon = NULL;
af4281dc2   Pavel Shilovsky   CIFS: Move inform...
3633
3634
  	ses = NULL;
  	server = NULL;
724d9f1cf   Pavel Shilovsky   CIFS: Simplify mo...
3635
3636
  	full_path = NULL;
  	tlink = NULL;
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
3637
  	xid = get_xid();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3638

63c038c29   Jeff Layton   cifs: move alloca...
3639
  	/* get a reference to a tcp session */
af4281dc2   Pavel Shilovsky   CIFS: Move inform...
3640
3641
3642
  	server = cifs_get_tcp_session(volume_info);
  	if (IS_ERR(server)) {
  		rc = PTR_ERR(server);
dd8544661   Al Viro   take bdi setup/de...
3643
  		bdi_destroy(&cifs_sb->bdi);
63c038c29   Jeff Layton   cifs: move alloca...
3644
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3645
  	}
141891f47   Steve French   SMB3: Add mount p...
3646
3647
3648
3649
3650
  	if ((volume_info->max_credits < 20) ||
  	     (volume_info->max_credits > 60000))
  		server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
  	else
  		server->max_credits = volume_info->max_credits;
36988c76f   Jeff Layton   cifs: move SMB se...
3651
  	/* get a reference to a SMB session */
af4281dc2   Pavel Shilovsky   CIFS: Move inform...
3652
3653
3654
3655
  	ses = cifs_get_smb_ses(server, volume_info);
  	if (IS_ERR(ses)) {
  		rc = PTR_ERR(ses);
  		ses = NULL;
36988c76f   Jeff Layton   cifs: move SMB se...
3656
  		goto mount_fail_check;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3657
  	}
50c2f7538   Steve French   [CIFS] whitespace...
3658

592fafe64   Steve French   Add resilienthand...
3659
  #ifdef CONFIG_CIFS_SMB2
b618f001a   Steve French   [SMB3] Enable che...
3660
3661
3662
3663
3664
3665
3666
  	if ((volume_info->persistent == true) && ((ses->server->capabilities &
  		SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) == 0)) {
  		cifs_dbg(VFS, "persistent handles not supported by server
  ");
  		rc = -EOPNOTSUPP;
  		goto mount_fail_check;
  	}
592fafe64   Steve French   Add resilienthand...
3667
  #endif /* CONFIG_CIFS_SMB2*/
d00c28de5   Jeff Layton   cifs: move tcon f...
3668
  	/* search for existing tcon to this server share */
af4281dc2   Pavel Shilovsky   CIFS: Move inform...
3669
  	tcon = cifs_get_tcon(ses, volume_info);
d00c28de5   Jeff Layton   cifs: move tcon f...
3670
3671
3672
  	if (IS_ERR(tcon)) {
  		rc = PTR_ERR(tcon);
  		tcon = NULL;
1bfe73c25   Igor Mammedov   Remote DFS root s...
3673
  		goto remote_path_check;
d00c28de5   Jeff Layton   cifs: move tcon f...
3674
  	}
1bfe73c25   Igor Mammedov   Remote DFS root s...
3675

d82c2df54   Steve French   [CIFS] minor clea...
3676
  	/* tell server which Unix caps we support */
29e20f9c6   Pavel Shilovsky   CIFS: Make CAP_* ...
3677
  	if (cap_unix(tcon->ses)) {
d82c2df54   Steve French   [CIFS] minor clea...
3678
3679
  		/* reset of caps checks mount to see if unix extensions
  		   disabled for just this mount */
2c6292ae4   Al Viro   cifs: don't pass ...
3680
  		reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
6848b7334   Steve French   [CIFS] When manda...
3681
3682
3683
3684
3685
3686
3687
  		if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
  		    (le64_to_cpu(tcon->fsUnixInfo.Capability) &
  		     CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
  			rc = -EACCES;
  			goto mount_fail_check;
  		}
  	} else
d82c2df54   Steve French   [CIFS] minor clea...
3688
  		tcon->unix_ext = 0; /* server does not support them */
c18c842b1   Steve French   [CIFS] Allow disa...
3689

af4281dc2   Pavel Shilovsky   CIFS: Move inform...
3690
3691
3692
  	/* do not care if a following call succeed - informational */
  	if (!tcon->ipc && server->ops->qfs_tcon)
  		server->ops->qfs_tcon(xid, tcon);
6848b7334   Steve French   [CIFS] When manda...
3693

24985c53d   Pavel Shilovsky   CIFS: Move r/wsiz...
3694
3695
  	cifs_sb->wsize = server->ops->negotiate_wsize(tcon, volume_info);
  	cifs_sb->rsize = server->ops->negotiate_rsize(tcon, volume_info);
f7910cbd9   Jeff Layton   cifs: clean up ws...
3696

66bfaadc3   Jeff Layton   cifs: tune bdi.ra...
3697
  	/* tune readahead according to rsize */
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
3698
  	cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_SIZE;
f7910cbd9   Jeff Layton   cifs: clean up ws...
3699

1bfe73c25   Igor Mammedov   Remote DFS root s...
3700
  remote_path_check:
c1508ca23   Sean Finney   cifs: Add support...
3701
3702
3703
3704
3705
3706
3707
3708
3709
  #ifdef CONFIG_CIFS_DFS_UPCALL
  	/*
  	 * Perform an unconditional check for whether there are DFS
  	 * referrals for this path without prefix, to provide support
  	 * for DFS referrals from w2k8 servers which don't seem to respond
  	 * with PATH_NOT_COVERED to requests that include the prefix.
  	 * Chase the referral if found, otherwise continue normally.
  	 */
  	if (referral_walks_count == 0) {
af4281dc2   Pavel Shilovsky   CIFS: Move inform...
3710
3711
  		int refrc = expand_dfs_referral(xid, ses, volume_info, cifs_sb,
  						false);
c1508ca23   Sean Finney   cifs: Add support...
3712
3713
3714
3715
3716
3717
  		if (!refrc) {
  			referral_walks_count++;
  			goto try_mount_again;
  		}
  	}
  #endif
f87d39d95   Steve French   [CIFS] Migrate fr...
3718
  	/* check if a whole path is not remote */
709456437   Jeff Layton   cifs: always do i...
3719
  	if (!rc && tcon) {
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
3720
3721
3722
3723
  		if (!server->ops->is_path_accessible) {
  			rc = -ENOSYS;
  			goto mount_fail_check;
  		}
6d3ea7e49   Steve French   CIFS: Make use of...
3724
3725
3726
3727
  		/*
  		 * cifs_build_path_to_root works only when we have a valid tcon
  		 */
  		full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
e4cce94c9   Igor Mammedov   [CIFS] Prevent OO...
3728
3729
3730
3731
  		if (full_path == NULL) {
  			rc = -ENOMEM;
  			goto mount_fail_check;
  		}
68889f269   Pavel Shilovsky   CIFS: Move is_pat...
3732
3733
  		rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
  						     full_path);
03ceace5c   Jeff Layton   cifs: fix check o...
3734
  		if (rc != 0 && rc != -EREMOTE) {
e4cce94c9   Igor Mammedov   [CIFS] Prevent OO...
3735
3736
3737
  			kfree(full_path);
  			goto mount_fail_check;
  		}
a6b5058fa   Aurelien Aptel   fs/cifs: make sha...
3738

d171356ff   Sachin Prabhu   Fix regression wh...
3739
3740
  		if (rc != -EREMOTE) {
  			rc = cifs_are_all_path_components_accessible(server,
a6b5058fa   Aurelien Aptel   fs/cifs: make sha...
3741
3742
  							     xid, tcon, cifs_sb,
  							     full_path);
d171356ff   Sachin Prabhu   Fix regression wh...
3743
3744
3745
3746
3747
3748
3749
  			if (rc != 0) {
  				cifs_dbg(VFS, "cannot query dirs between root and final path, "
  					 "enabling CIFS_MOUNT_USE_PREFIX_PATH
  ");
  				cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
  				rc = 0;
  			}
a6b5058fa   Aurelien Aptel   fs/cifs: make sha...
3750
  		}
e4cce94c9   Igor Mammedov   [CIFS] Prevent OO...
3751
3752
  		kfree(full_path);
  	}
1bfe73c25   Igor Mammedov   Remote DFS root s...
3753
3754
  	/* get referral if needed */
  	if (rc == -EREMOTE) {
d036f50fc   Steve French   [CIFS] Fix build ...
3755
  #ifdef CONFIG_CIFS_DFS_UPCALL
5c2503a8e   Igor Mammedov   Added loop check ...
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
  		if (referral_walks_count > MAX_NESTED_LINKS) {
  			/*
  			 * BB: when we implement proper loop detection,
  			 *     we will remove this check. But now we need it
  			 *     to prevent an indefinite loop if 'DFS tree' is
  			 *     misconfigured (i.e. has loops).
  			 */
  			rc = -ELOOP;
  			goto mount_fail_check;
  		}
1bfe73c25   Igor Mammedov   Remote DFS root s...
3766

af4281dc2   Pavel Shilovsky   CIFS: Move inform...
3767
  		rc = expand_dfs_referral(xid, ses, volume_info, cifs_sb, true);
7b91e2661   Jeff Layton   cifs: fix error h...
3768

dd6139458   Sean Finney   cifs: Extract DFS...
3769
  		if (!rc) {
5c2503a8e   Igor Mammedov   Added loop check ...
3770
  			referral_walks_count++;
1bfe73c25   Igor Mammedov   Remote DFS root s...
3771
3772
  			goto try_mount_again;
  		}
dd6139458   Sean Finney   cifs: Extract DFS...
3773
  		goto mount_fail_check;
d036f50fc   Steve French   [CIFS] Fix build ...
3774
3775
3776
  #else /* No DFS support, return error on mount */
  		rc = -EOPNOTSUPP;
  #endif
1bfe73c25   Igor Mammedov   Remote DFS root s...
3777
  	}
9d002df49   Jeff Layton   cifs: add routine...
3778
3779
3780
3781
3782
3783
3784
3785
3786
  	if (rc)
  		goto mount_fail_check;
  
  	/* now, hang the tcon off of the superblock */
  	tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
  	if (tlink == NULL) {
  		rc = -ENOMEM;
  		goto mount_fail_check;
  	}
af4281dc2   Pavel Shilovsky   CIFS: Move inform...
3787
  	tlink->tl_uid = ses->linux_uid;
9d002df49   Jeff Layton   cifs: add routine...
3788
3789
3790
3791
  	tlink->tl_tcon = tcon;
  	tlink->tl_time = jiffies;
  	set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
  	set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
b647c35f7   Jeff Layton   cifs: convert tli...
3792
  	cifs_sb->master_tlink = tlink;
9d002df49   Jeff Layton   cifs: add routine...
3793
  	spin_lock(&cifs_sb->tlink_tree_lock);
b647c35f7   Jeff Layton   cifs: convert tli...
3794
  	tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
9d002df49   Jeff Layton   cifs: add routine...
3795
  	spin_unlock(&cifs_sb->tlink_tree_lock);
413e661c1   Jeff Layton   cifs: store point...
3796

da472fc84   Jeff Layton   cifs: add new cif...
3797
  	queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
2de970ff6   Jeff Layton   cifs: implement r...
3798
  				TLINK_IDLE_EXPIRE);
1bfe73c25   Igor Mammedov   Remote DFS root s...
3799
3800
3801
  mount_fail_check:
  	/* on error free sesinfo and tcon struct if needed */
  	if (rc) {
1bfe73c25   Igor Mammedov   Remote DFS root s...
3802
  		/* If find_unc succeeded then rc == 0 so we can not end */
25985edce   Lucas De Marchi   Fix common misspe...
3803
  		/* up accidentally freeing someone elses tcon struct */
1bfe73c25   Igor Mammedov   Remote DFS root s...
3804
3805
  		if (tcon)
  			cifs_put_tcon(tcon);
af4281dc2   Pavel Shilovsky   CIFS: Move inform...
3806
3807
  		else if (ses)
  			cifs_put_smb_ses(ses);
1bfe73c25   Igor Mammedov   Remote DFS root s...
3808
  		else
48f9526f4   Pavel Shilovsky   CIFS: Fix a possi...
3809
  			cifs_put_tcp_session(server, 0);
dd8544661   Al Viro   take bdi setup/de...
3810
  		bdi_destroy(&cifs_sb->bdi);
1bfe73c25   Igor Mammedov   Remote DFS root s...
3811
  	}
70fe7dc05   Jeff Layton   [CIFS] clean up e...
3812
  out:
6d5786a34   Pavel Shilovsky   CIFS: Rename Get/...
3813
  	free_xid(xid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3814
3815
  	return rc;
  }
8d1bca328   Jeff Layton   cifs: correctly h...
3816
3817
3818
3819
  /*
   * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon
   * pointer may be NULL.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3820
  int
2e6e02ab6   Pavel Shilovsky   CIFS: Move protoc...
3821
  CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
96daf2b09   Steve French   [CIFS] Rename thr...
3822
  	 const char *tree, struct cifs_tcon *tcon,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3823
3824
3825
3826
3827
3828
3829
3830
  	 const struct nls_table *nls_codepage)
  {
  	struct smb_hdr *smb_buffer;
  	struct smb_hdr *smb_buffer_response;
  	TCONX_REQ *pSMB;
  	TCONX_RSP *pSMBr;
  	unsigned char *bcc_ptr;
  	int rc = 0;
690c522fa   Jeff Layton   cifs: use get/put...
3831
3832
  	int length;
  	__u16 bytes_left, count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3833
3834
3835
3836
3837
  
  	if (ses == NULL)
  		return -EIO;
  
  	smb_buffer = cifs_buf_get();
ca43e3bee   Steve French   [CIFS] Fix checkp...
3838
  	if (smb_buffer == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3839
  		return -ENOMEM;
ca43e3bee   Steve French   [CIFS] Fix checkp...
3840

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3841
3842
3843
3844
  	smb_buffer_response = smb_buffer;
  
  	header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
  			NULL /*no tid */ , 4 /*wct */ );
1982c344f   Steve French   [CIFS] Ensure tha...
3845

882573606   Pavel Shilovsky   CIFS: Move get_ne...
3846
  	smb_buffer->Mid = get_next_mid(ses->server);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3847
3848
3849
3850
3851
3852
  	smb_buffer->Uid = ses->Suid;
  	pSMB = (TCONX_REQ *) smb_buffer;
  	pSMBr = (TCONX_RSP *) smb_buffer_response;
  
  	pSMB->AndXCommand = 0xFF;
  	pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3853
  	bcc_ptr = &pSMB->Password[0];
8d1bca328   Jeff Layton   cifs: correctly h...
3854
  	if (!tcon || (ses->server->sec_mode & SECMODE_USER)) {
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3855
  		pSMB->PasswordLength = cpu_to_le16(1);	/* minimum */
7c7b25bc8   Steve French   [CIFS] Support fo...
3856
  		*bcc_ptr = 0; /* password is null byte */
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3857
  		bcc_ptr++;              /* skip password */
7c7b25bc8   Steve French   [CIFS] Support fo...
3858
  		/* already aligned so no need to do it below */
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3859
  	} else {
540b2e377   Shirish Pargaonkar   cifs: Fix regress...
3860
  		pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3861
3862
3863
  		/* BB FIXME add code to fail this if NTLMv2 or Kerberos
  		   specified as required (when that support is added to
  		   the vfs in the future) as only NTLM or the much
7c7b25bc8   Steve French   [CIFS] Support fo...
3864
  		   weaker LANMAN (which we do not send by default) is accepted
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3865
3866
  		   by Samba (not sure whether other servers allow
  		   NTLMv2 password here) */
7c7b25bc8   Steve French   [CIFS] Support fo...
3867
  #ifdef CONFIG_CIFS_WEAK_PW_HASH
04912d6a2   Jeff Layton   cifs: rename "ext...
3868
  		if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
3f618223d   Jeff Layton   move sectype to t...
3869
  		    (ses->sectype == LANMAN))
d3ba50b17   Shirish Pargaonkar   NTLM auth and sig...
3870
  			calc_lanman_hash(tcon->password, ses->server->cryptkey,
96daf2b09   Steve French   [CIFS] Rename thr...
3871
  					 ses->server->sec_mode &
4e53a3fb9   Jeff Layton   cifs: have calc_l...
3872
3873
  					    SECMODE_PW_ENCRYPT ? true : false,
  					 bcc_ptr);
7c7b25bc8   Steve French   [CIFS] Support fo...
3874
3875
  		else
  #endif /* CIFS_WEAK_PW_HASH */
ee2c92585   Shirish Pargaonkar   cifs: More crypto...
3876
  		rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
9ef5992e4   Shirish Pargaonkar   cifs: Assume pass...
3877
  					bcc_ptr, nls_codepage);
f3a31a2bb   Steve French   Don't ignore erro...
3878
3879
3880
3881
3882
3883
3884
  		if (rc) {
  			cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d
  ",
  				 __func__, rc);
  			cifs_buf_release(smb_buffer);
  			return rc;
  		}
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3885

540b2e377   Shirish Pargaonkar   cifs: Fix regress...
3886
  		bcc_ptr += CIFS_AUTH_RESP_SIZE;
fb8c4b14d   Steve French   [CIFS] whitespace...
3887
  		if (ses->capabilities & CAP_UNICODE) {
7c7b25bc8   Steve French   [CIFS] Support fo...
3888
3889
3890
3891
  			/* must align unicode strings */
  			*bcc_ptr = 0; /* null byte password */
  			bcc_ptr++;
  		}
eeac8047f   Steve French   [CIFS] Fix CIFS t...
3892
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3893

38d77c50b   Jeff Layton   cifs: track the e...
3894
  	if (ses->server->sign)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
  		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
  
  	if (ses->capabilities & CAP_STATUS32) {
  		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
  	}
  	if (ses->capabilities & CAP_DFS) {
  		smb_buffer->Flags2 |= SMBFLG2_DFS;
  	}
  	if (ses->capabilities & CAP_UNICODE) {
  		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
  		length =
acbbb76a2   Steve French   CIFS: Rename *UCS...
3906
  		    cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
50c2f7538   Steve French   [CIFS] whitespace...
3907
  			6 /* max utf8 char length in bytes */ *
a878fb221   Steve French   [CIFS] Do not lim...
3908
3909
  			(/* server len*/ + 256 /* share len */), nls_codepage);
  		bcc_ptr += 2 * length;	/* convert num 16 bit words to bytes */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3910
3911
  		bcc_ptr += 2;	/* skip trailing null */
  	} else {		/* ASCII */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3912
3913
3914
3915
3916
3917
3918
  		strcpy(bcc_ptr, tree);
  		bcc_ptr += strlen(tree) + 1;
  	}
  	strcpy(bcc_ptr, "?????");
  	bcc_ptr += strlen("?????");
  	bcc_ptr += 1;
  	count = bcc_ptr - &pSMB->Password[0];
be8e3b004   Steve French   consistently use ...
3919
3920
  	pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
  					pSMB->hdr.smb_buf_length) + count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3921
  	pSMB->ByteCount = cpu_to_le16(count);
133672efb   Steve French   [CIFS] Fix buffer...
3922
  	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
7749981ec   Jeff Layton   cifs: remove code...
3923
  			 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3924

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3925
3926
  	/* above now done in SendReceive */
  	if ((rc == 0) && (tcon != NULL)) {
0e0d2cf32   Steve French   [CIFS] Remove spa...
3927
  		bool is_unicode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3928
  		tcon->tidStatus = CifsGood;
3b7952109   Steve French   [CIFS] Fix cifs r...
3929
  		tcon->need_reconnect = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3930
3931
  		tcon->tid = smb_buffer_response->Tid;
  		bcc_ptr = pByteArea(smb_buffer_response);
690c522fa   Jeff Layton   cifs: use get/put...
3932
  		bytes_left = get_bcc(smb_buffer_response);
cc20c031b   Jeff Layton   cifs: convert CIF...
3933
  		length = strnlen(bcc_ptr, bytes_left - 2);
0e0d2cf32   Steve French   [CIFS] Remove spa...
3934
3935
3936
3937
  		if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
  			is_unicode = true;
  		else
  			is_unicode = false;
cc20c031b   Jeff Layton   cifs: convert CIF...
3938

50c2f7538   Steve French   [CIFS] whitespace...
3939
  		/* skip service field (NB: this field is always ASCII) */
7f8ed420f   Steve French   [CIFS] CIFS suppo...
3940
3941
3942
  		if (length == 3) {
  			if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
  			    (bcc_ptr[2] == 'C')) {
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3943
3944
  				cifs_dbg(FYI, "IPC connection
  ");
7f8ed420f   Steve French   [CIFS] CIFS suppo...
3945
3946
3947
3948
3949
  				tcon->ipc = 1;
  			}
  		} else if (length == 2) {
  			if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
  				/* the most common case */
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3950
3951
  				cifs_dbg(FYI, "disk share connection
  ");
7f8ed420f   Steve French   [CIFS] CIFS suppo...
3952
3953
  			}
  		}
50c2f7538   Steve French   [CIFS] whitespace...
3954
  		bcc_ptr += length + 1;
cc20c031b   Jeff Layton   cifs: convert CIF...
3955
  		bytes_left -= (length + 1);
46b51d083   Zhao Hongjiang   cifs: using strlc...
3956
  		strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
cc20c031b   Jeff Layton   cifs: convert CIF...
3957
3958
  
  		/* mostly informational -- no need to fail on error here */
90a98b2f3   Jeff Layton   cifs: free native...
3959
  		kfree(tcon->nativeFileSystem);
acbbb76a2   Steve French   CIFS: Rename *UCS...
3960
  		tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
0e0d2cf32   Steve French   [CIFS] Remove spa...
3961
  						      bytes_left, is_unicode,
cc20c031b   Jeff Layton   cifs: convert CIF...
3962
  						      nls_codepage);
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3963
3964
  		cifs_dbg(FYI, "nativeFileSystem=%s
  ", tcon->nativeFileSystem);
cc20c031b   Jeff Layton   cifs: convert CIF...
3965

fb8c4b14d   Steve French   [CIFS] whitespace...
3966
  		if ((smb_buffer_response->WordCount == 3) ||
1a4e15a04   Steve French   [CIFS] Missing fl...
3967
3968
  			 (smb_buffer_response->WordCount == 7))
  			/* field is in same location */
3979877e5   Steve French   [CIFS] Support fo...
3969
3970
3971
  			tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
  		else
  			tcon->Flags = 0;
f96637be0   Joe Perches   [CIFS] cifs: Rena...
3972
3973
  		cifs_dbg(FYI, "Tcon flags: 0x%x
  ", tcon->Flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3974
  	} else if ((rc == 0) && tcon == NULL) {
50c2f7538   Steve French   [CIFS] whitespace...
3975
  		/* all we need to save for IPC$ connection */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3976
3977
  		ses->ipc_tid = smb_buffer_response->Tid;
  	}
a8a11d399   Mariusz Kozlowski   [CIFS] remove som...
3978
  	cifs_buf_release(smb_buffer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3979
3980
  	return rc;
  }
2e32cf5ef   Al Viro   cifs: rcu-delay u...
3981
3982
3983
3984
3985
3986
  static void delayed_free(struct rcu_head *p)
  {
  	struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
  	unload_nls(sbi->local_nls);
  	kfree(sbi);
  }
2a9b99516   Al Viro   sanitize cifs_umo...
3987
3988
  void
  cifs_umount(struct cifs_sb_info *cifs_sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3989
  {
b647c35f7   Jeff Layton   cifs: convert tli...
3990
3991
3992
  	struct rb_root *root = &cifs_sb->tlink_tree;
  	struct rb_node *node;
  	struct tcon_link *tlink;
9d002df49   Jeff Layton   cifs: add routine...
3993

2de970ff6   Jeff Layton   cifs: implement r...
3994
  	cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
b647c35f7   Jeff Layton   cifs: convert tli...
3995
3996
3997
3998
3999
4000
  	spin_lock(&cifs_sb->tlink_tree_lock);
  	while ((node = rb_first(root))) {
  		tlink = rb_entry(node, struct tcon_link, tl_rbnode);
  		cifs_get_tlink(tlink);
  		clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
  		rb_erase(node, root);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4001

b647c35f7   Jeff Layton   cifs: convert tli...
4002
4003
4004
4005
4006
  		spin_unlock(&cifs_sb->tlink_tree_lock);
  		cifs_put_tlink(tlink);
  		spin_lock(&cifs_sb->tlink_tree_lock);
  	}
  	spin_unlock(&cifs_sb->tlink_tree_lock);
50c2f7538   Steve French   [CIFS] whitespace...
4007

dd8544661   Al Viro   take bdi setup/de...
4008
  	bdi_destroy(&cifs_sb->bdi);
d757d71bf   Al Viro   cifs: pull freein...
4009
  	kfree(cifs_sb->mountdata);
a6b5058fa   Aurelien Aptel   fs/cifs: make sha...
4010
  	kfree(cifs_sb->prepath);
2e32cf5ef   Al Viro   cifs: rcu-delay u...
4011
  	call_rcu(&cifs_sb->rcu, delayed_free);
50c2f7538   Steve French   [CIFS] whitespace...
4012
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4013

286170aa2   Pavel Shilovsky   CIFS: Move protoc...
4014
4015
  int
  cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4016
4017
  {
  	int rc = 0;
198b56827   Jeff Layton   cifs: break negot...
4018
  	struct TCP_Server_Info *server = ses->server;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4019

286170aa2   Pavel Shilovsky   CIFS: Move protoc...
4020
4021
  	if (!server->ops->need_neg || !server->ops->negotiate)
  		return -ENOSYS;
198b56827   Jeff Layton   cifs: break negot...
4022
  	/* only send once per connect */
286170aa2   Pavel Shilovsky   CIFS: Move protoc...
4023
  	if (!server->ops->need_neg(server))
198b56827   Jeff Layton   cifs: break negot...
4024
  		return 0;
452757897   Pavel Shilovsky   CIFS: Move add/se...
4025
  	set_credits(server, 1);
286170aa2   Pavel Shilovsky   CIFS: Move protoc...
4026
4027
  
  	rc = server->ops->negotiate(xid, ses);
198b56827   Jeff Layton   cifs: break negot...
4028
4029
  	if (rc == 0) {
  		spin_lock(&GlobalMid_Lock);
7fdbaa1b8   Jeff Layton   cifs: don't allow...
4030
  		if (server->tcpStatus == CifsNeedNegotiate)
198b56827   Jeff Layton   cifs: break negot...
4031
4032
4033
4034
  			server->tcpStatus = CifsGood;
  		else
  			rc = -EHOSTDOWN;
  		spin_unlock(&GlobalMid_Lock);
198b56827   Jeff Layton   cifs: break negot...
4035
4036
4037
4038
  	}
  
  	return rc;
  }
58c45c58a   Pavel Shilovsky   CIFS: Move protoc...
4039
4040
4041
  int
  cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
  		   struct nls_table *nls_info)
198b56827   Jeff Layton   cifs: break negot...
4042
  {
58c45c58a   Pavel Shilovsky   CIFS: Move protoc...
4043
  	int rc = -ENOSYS;
198b56827   Jeff Layton   cifs: break negot...
4044
  	struct TCP_Server_Info *server = ses->server;
26b994fad   Steve French   [CIFS] Code clean...
4045

198b56827   Jeff Layton   cifs: break negot...
4046
  	ses->capabilities = server->capabilities;
26b994fad   Steve French   [CIFS] Code clean...
4047
  	if (linuxExtEnabled == 0)
29e20f9c6   Pavel Shilovsky   CIFS: Make CAP_* ...
4048
  		ses->capabilities &= (~server->vals->cap_unix);
20418acd6   Steve French   [CIFS] Remove old...
4049

f96637be0   Joe Perches   [CIFS] cifs: Rena...
4050
4051
  	cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d
  ",
96daf2b09   Steve French   [CIFS] Rename thr...
4052
  		 server->sec_mode, server->capabilities, server->timeAdj);
cb7691b64   Jeff Layton   cifs: add local s...
4053

58c45c58a   Pavel Shilovsky   CIFS: Move protoc...
4054
4055
  	if (server->ops->sess_setup)
  		rc = server->ops->sess_setup(xid, ses, nls_info);
d4e63bd6e   Shirish Pargaonkar   cifs: Process pos...
4056
  	if (rc)
f96637be0   Joe Perches   [CIFS] cifs: Rena...
4057
4058
  		cifs_dbg(VFS, "Send error in SessSetup = %d
  ", rc);
21e733930   Shirish Pargaonkar   NTLM auth and sig...
4059

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4060
4061
  	return rc;
  }
8a8798a5f   Jeff Layton   cifs: fetch crede...
4062
4063
4064
  static int
  cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
  {
3f618223d   Jeff Layton   move sectype to t...
4065
4066
4067
4068
  	vol->sectype = ses->sectype;
  
  	/* krb5 is special, since we don't need username or pw */
  	if (vol->sectype == Kerberos)
8a8798a5f   Jeff Layton   cifs: fetch crede...
4069
  		return 0;
8a8798a5f   Jeff Layton   cifs: fetch crede...
4070
4071
4072
  
  	return cifs_set_cifscreds(vol, ses);
  }
96daf2b09   Steve French   [CIFS] Rename thr...
4073
  static struct cifs_tcon *
6d4a08320   Eric W. Biederman   cifs: Convert str...
4074
  cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
9d002df49   Jeff Layton   cifs: add routine...
4075
  {
8a8798a5f   Jeff Layton   cifs: fetch crede...
4076
  	int rc;
96daf2b09   Steve French   [CIFS] Rename thr...
4077
4078
4079
  	struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
  	struct cifs_ses *ses;
  	struct cifs_tcon *tcon = NULL;
9d002df49   Jeff Layton   cifs: add routine...
4080
  	struct smb_vol *vol_info;
9d002df49   Jeff Layton   cifs: add routine...
4081
4082
  
  	vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
803ab9776   Dan Carpenter   cifs: NULL derefe...
4083
4084
  	if (vol_info == NULL)
  		return ERR_PTR(-ENOMEM);
9d002df49   Jeff Layton   cifs: add routine...
4085

9d002df49   Jeff Layton   cifs: add routine...
4086
4087
4088
4089
4090
4091
4092
4093
  	vol_info->local_nls = cifs_sb->local_nls;
  	vol_info->linux_uid = fsuid;
  	vol_info->cred_uid = fsuid;
  	vol_info->UNC = master_tcon->treeName;
  	vol_info->retry = master_tcon->retry;
  	vol_info->nocase = master_tcon->nocase;
  	vol_info->local_lease = master_tcon->local_lease;
  	vol_info->no_linux_ext = !master_tcon->unix_ext;
28e11bd86   Jeff Layton   cifs: add new fie...
4094
4095
  	vol_info->sectype = master_tcon->ses->sectype;
  	vol_info->sign = master_tcon->ses->sign;
9d002df49   Jeff Layton   cifs: add routine...
4096

8a8798a5f   Jeff Layton   cifs: fetch crede...
4097
4098
4099
4100
4101
  	rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
  	if (rc) {
  		tcon = ERR_PTR(rc);
  		goto out;
  	}
9d002df49   Jeff Layton   cifs: add routine...
4102
4103
  
  	/* get a reference for the same TCP session */
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
4104
  	spin_lock(&cifs_tcp_ses_lock);
9d002df49   Jeff Layton   cifs: add routine...
4105
  	++master_tcon->ses->server->srv_count;
3f9bcca78   Suresh Jayaraman   cifs: convert cif...
4106
  	spin_unlock(&cifs_tcp_ses_lock);
9d002df49   Jeff Layton   cifs: add routine...
4107
4108
4109
  
  	ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
  	if (IS_ERR(ses)) {
96daf2b09   Steve French   [CIFS] Rename thr...
4110
  		tcon = (struct cifs_tcon *)ses;
48f9526f4   Pavel Shilovsky   CIFS: Fix a possi...
4111
  		cifs_put_tcp_session(master_tcon->ses->server, 0);
9d002df49   Jeff Layton   cifs: add routine...
4112
4113
4114
4115
4116
4117
4118
4119
  		goto out;
  	}
  
  	tcon = cifs_get_tcon(ses, vol_info);
  	if (IS_ERR(tcon)) {
  		cifs_put_smb_ses(ses);
  		goto out;
  	}
29e20f9c6   Pavel Shilovsky   CIFS: Make CAP_* ...
4120
  	if (cap_unix(ses))
9d002df49   Jeff Layton   cifs: add routine...
4121
4122
  		reset_cifs_unix_caps(0, tcon, NULL, vol_info);
  out:
8a8798a5f   Jeff Layton   cifs: fetch crede...
4123
4124
  	kfree(vol_info->username);
  	kfree(vol_info->password);
9d002df49   Jeff Layton   cifs: add routine...
4125
4126
4127
4128
  	kfree(vol_info);
  
  	return tcon;
  }
96daf2b09   Steve French   [CIFS] Rename thr...
4129
  struct cifs_tcon *
9d002df49   Jeff Layton   cifs: add routine...
4130
4131
4132
4133
  cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
  {
  	return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
  }
b647c35f7   Jeff Layton   cifs: convert tli...
4134
4135
  /* find and return a tlink with given uid */
  static struct tcon_link *
6d4a08320   Eric W. Biederman   cifs: Convert str...
4136
  tlink_rb_search(struct rb_root *root, kuid_t uid)
b647c35f7   Jeff Layton   cifs: convert tli...
4137
4138
4139
4140
4141
4142
  {
  	struct rb_node *node = root->rb_node;
  	struct tcon_link *tlink;
  
  	while (node) {
  		tlink = rb_entry(node, struct tcon_link, tl_rbnode);
6d4a08320   Eric W. Biederman   cifs: Convert str...
4143
  		if (uid_gt(tlink->tl_uid, uid))
b647c35f7   Jeff Layton   cifs: convert tli...
4144
  			node = node->rb_left;
6d4a08320   Eric W. Biederman   cifs: Convert str...
4145
  		else if (uid_lt(tlink->tl_uid, uid))
b647c35f7   Jeff Layton   cifs: convert tli...
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
  			node = node->rb_right;
  		else
  			return tlink;
  	}
  	return NULL;
  }
  
  /* insert a tcon_link into the tree */
  static void
  tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
  {
  	struct rb_node **new = &(root->rb_node), *parent = NULL;
  	struct tcon_link *tlink;
  
  	while (*new) {
  		tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
  		parent = *new;
6d4a08320   Eric W. Biederman   cifs: Convert str...
4163
  		if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
b647c35f7   Jeff Layton   cifs: convert tli...
4164
4165
4166
4167
4168
4169
4170
4171
  			new = &((*new)->rb_left);
  		else
  			new = &((*new)->rb_right);
  	}
  
  	rb_link_node(&new_tlink->tl_rbnode, parent, new);
  	rb_insert_color(&new_tlink->tl_rbnode, root);
  }
9d002df49   Jeff Layton   cifs: add routine...
4172
4173
4174
4175
4176
4177
4178
  /*
   * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
   * current task.
   *
   * If the superblock doesn't refer to a multiuser mount, then just return
   * the master tcon for the mount.
   *
6ef933a38   Suresh Jayaraman   cifs: trivial com...
4179
   * First, search the rbtree for an existing tcon for this fsuid. If one
9d002df49   Jeff Layton   cifs: add routine...
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
   * exists, then check to see if it's pending construction. If it is then wait
   * for construction to complete. Once it's no longer pending, check to see if
   * it failed and either return an error or retry construction, depending on
   * the timeout.
   *
   * If one doesn't exist then insert a new tcon_link struct into the tree and
   * try to construct a new one.
   */
  struct tcon_link *
  cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
  {
  	int ret;
6d4a08320   Eric W. Biederman   cifs: Convert str...
4192
  	kuid_t fsuid = current_fsuid();
9d002df49   Jeff Layton   cifs: add routine...
4193
4194
4195
4196
4197
4198
  	struct tcon_link *tlink, *newtlink;
  
  	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
  		return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
  
  	spin_lock(&cifs_sb->tlink_tree_lock);
b647c35f7   Jeff Layton   cifs: convert tli...
4199
  	tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
9d002df49   Jeff Layton   cifs: add routine...
4200
4201
4202
4203
4204
4205
4206
4207
  	if (tlink)
  		cifs_get_tlink(tlink);
  	spin_unlock(&cifs_sb->tlink_tree_lock);
  
  	if (tlink == NULL) {
  		newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
  		if (newtlink == NULL)
  			return ERR_PTR(-ENOMEM);
b647c35f7   Jeff Layton   cifs: convert tli...
4208
  		newtlink->tl_uid = fsuid;
9d002df49   Jeff Layton   cifs: add routine...
4209
4210
4211
4212
  		newtlink->tl_tcon = ERR_PTR(-EACCES);
  		set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
  		set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
  		cifs_get_tlink(newtlink);
9d002df49   Jeff Layton   cifs: add routine...
4213
4214
  		spin_lock(&cifs_sb->tlink_tree_lock);
  		/* was one inserted after previous search? */
b647c35f7   Jeff Layton   cifs: convert tli...
4215
  		tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
9d002df49   Jeff Layton   cifs: add routine...
4216
4217
4218
  		if (tlink) {
  			cifs_get_tlink(tlink);
  			spin_unlock(&cifs_sb->tlink_tree_lock);
9d002df49   Jeff Layton   cifs: add routine...
4219
4220
4221
  			kfree(newtlink);
  			goto wait_for_construction;
  		}
9d002df49   Jeff Layton   cifs: add routine...
4222
  		tlink = newtlink;
b647c35f7   Jeff Layton   cifs: convert tli...
4223
4224
  		tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
  		spin_unlock(&cifs_sb->tlink_tree_lock);
9d002df49   Jeff Layton   cifs: add routine...
4225
4226
4227
  	} else {
  wait_for_construction:
  		ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
9d002df49   Jeff Layton   cifs: add routine...
4228
4229
4230
  				  TASK_INTERRUPTIBLE);
  		if (ret) {
  			cifs_put_tlink(tlink);
743162013   NeilBrown   sched: Remove pro...
4231
  			return ERR_PTR(-ERESTARTSYS);
9d002df49   Jeff Layton   cifs: add routine...
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
  		}
  
  		/* if it's good, return it */
  		if (!IS_ERR(tlink->tl_tcon))
  			return tlink;
  
  		/* return error if we tried this already recently */
  		if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
  			cifs_put_tlink(tlink);
  			return ERR_PTR(-EACCES);
  		}
  
  		if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
  			goto wait_for_construction;
  	}
  
  	tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
  	clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
  	wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
  
  	if (IS_ERR(tlink->tl_tcon)) {
  		cifs_put_tlink(tlink);
  		return ERR_PTR(-EACCES);
  	}
  
  	return tlink;
  }
2de970ff6   Jeff Layton   cifs: implement r...
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
  
  /*
   * periodic workqueue job that scans tcon_tree for a superblock and closes
   * out tcons.
   */
  static void
  cifs_prune_tlinks(struct work_struct *work)
  {
  	struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
  						    prune_tlinks.work);
b647c35f7   Jeff Layton   cifs: convert tli...
4269
4270
4271
4272
  	struct rb_root *root = &cifs_sb->tlink_tree;
  	struct rb_node *node = rb_first(root);
  	struct rb_node *tmp;
  	struct tcon_link *tlink;
2de970ff6   Jeff Layton   cifs: implement r...
4273

b647c35f7   Jeff Layton   cifs: convert tli...
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
  	/*
  	 * Because we drop the spinlock in the loop in order to put the tlink
  	 * it's not guarded against removal of links from the tree. The only
  	 * places that remove entries from the tree are this function and
  	 * umounts. Because this function is non-reentrant and is canceled
  	 * before umount can proceed, this is safe.
  	 */
  	spin_lock(&cifs_sb->tlink_tree_lock);
  	node = rb_first(root);
  	while (node != NULL) {
  		tmp = node;
  		node = rb_next(tmp);
  		tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
  
  		if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
  		    atomic_read(&tlink->tl_count) != 0 ||
  		    time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
  			continue;
2de970ff6   Jeff Layton   cifs: implement r...
4292

b647c35f7   Jeff Layton   cifs: convert tli...
4293
4294
4295
4296
4297
4298
4299
4300
4301
  		cifs_get_tlink(tlink);
  		clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
  		rb_erase(tmp, root);
  
  		spin_unlock(&cifs_sb->tlink_tree_lock);
  		cifs_put_tlink(tlink);
  		spin_lock(&cifs_sb->tlink_tree_lock);
  	}
  	spin_unlock(&cifs_sb->tlink_tree_lock);
2de970ff6   Jeff Layton   cifs: implement r...
4302

da472fc84   Jeff Layton   cifs: add new cif...
4303
  	queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
2de970ff6   Jeff Layton   cifs: implement r...
4304
4305
  				TLINK_IDLE_EXPIRE);
  }