diff options
Diffstat (limited to 'fs/cifs/cifsfs.c')
-rw-r--r-- | fs/cifs/cifsfs.c | 583 |
1 files changed, 405 insertions, 178 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index b7431afdd76d..bc4b12ca537b 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -35,7 +35,8 @@ | |||
35 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
36 | #include <linux/kthread.h> | 36 | #include <linux/kthread.h> |
37 | #include <linux/freezer.h> | 37 | #include <linux/freezer.h> |
38 | #include <linux/smp_lock.h> | 38 | #include <linux/namei.h> |
39 | #include <net/ipv6.h> | ||
39 | #include "cifsfs.h" | 40 | #include "cifsfs.h" |
40 | #include "cifspdu.h" | 41 | #include "cifspdu.h" |
41 | #define DECLARE_GLOBALS_HERE | 42 | #define DECLARE_GLOBALS_HERE |
@@ -53,7 +54,6 @@ int cifsFYI = 0; | |||
53 | int cifsERROR = 1; | 54 | int cifsERROR = 1; |
54 | int traceSMB = 0; | 55 | int traceSMB = 0; |
55 | unsigned int oplockEnabled = 1; | 56 | unsigned int oplockEnabled = 1; |
56 | unsigned int experimEnabled = 0; | ||
57 | unsigned int linuxExtEnabled = 1; | 57 | unsigned int linuxExtEnabled = 1; |
58 | unsigned int lookupCacheEnabled = 1; | 58 | unsigned int lookupCacheEnabled = 1; |
59 | unsigned int multiuser_mount = 0; | 59 | unsigned int multiuser_mount = 0; |
@@ -77,71 +77,59 @@ unsigned int cifs_max_pending = CIFS_MAX_REQ; | |||
77 | module_param(cifs_max_pending, int, 0); | 77 | module_param(cifs_max_pending, int, 0); |
78 | MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. " | 78 | MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. " |
79 | "Default: 50 Range: 2 to 256"); | 79 | "Default: 50 Range: 2 to 256"); |
80 | 80 | unsigned short echo_retries = 5; | |
81 | module_param(echo_retries, ushort, 0644); | ||
82 | MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and " | ||
83 | "reconnecting server. Default: 5. 0 means " | ||
84 | "never reconnect."); | ||
81 | extern mempool_t *cifs_sm_req_poolp; | 85 | extern mempool_t *cifs_sm_req_poolp; |
82 | extern mempool_t *cifs_req_poolp; | 86 | extern mempool_t *cifs_req_poolp; |
83 | extern mempool_t *cifs_mid_poolp; | 87 | extern mempool_t *cifs_mid_poolp; |
84 | 88 | ||
89 | void | ||
90 | cifs_sb_active(struct super_block *sb) | ||
91 | { | ||
92 | struct cifs_sb_info *server = CIFS_SB(sb); | ||
93 | |||
94 | if (atomic_inc_return(&server->active) == 1) | ||
95 | atomic_inc(&sb->s_active); | ||
96 | } | ||
97 | |||
98 | void | ||
99 | cifs_sb_deactive(struct super_block *sb) | ||
100 | { | ||
101 | struct cifs_sb_info *server = CIFS_SB(sb); | ||
102 | |||
103 | if (atomic_dec_and_test(&server->active)) | ||
104 | deactivate_super(sb); | ||
105 | } | ||
106 | |||
85 | static int | 107 | static int |
86 | cifs_read_super(struct super_block *sb, void *data, | 108 | cifs_read_super(struct super_block *sb) |
87 | const char *devname, int silent) | ||
88 | { | 109 | { |
89 | struct inode *inode; | 110 | struct inode *inode; |
90 | struct cifs_sb_info *cifs_sb; | 111 | struct cifs_sb_info *cifs_sb; |
91 | int rc = 0; | 112 | int rc = 0; |
92 | 113 | ||
93 | /* BB should we make this contingent on mount parm? */ | ||
94 | sb->s_flags |= MS_NODIRATIME | MS_NOATIME; | ||
95 | sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); | ||
96 | cifs_sb = CIFS_SB(sb); | 114 | cifs_sb = CIFS_SB(sb); |
97 | if (cifs_sb == NULL) | ||
98 | return -ENOMEM; | ||
99 | 115 | ||
100 | rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY); | 116 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL) |
101 | if (rc) { | 117 | sb->s_flags |= MS_POSIXACL; |
102 | kfree(cifs_sb); | ||
103 | return rc; | ||
104 | } | ||
105 | 118 | ||
106 | #ifdef CONFIG_CIFS_DFS_UPCALL | 119 | if (cifs_sb_master_tcon(cifs_sb)->ses->capabilities & CAP_LARGE_FILES) |
107 | /* copy mount params to sb for use in submounts */ | 120 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
108 | /* BB: should we move this after the mount so we | 121 | else |
109 | * do not have to do the copy on failed mounts? | 122 | sb->s_maxbytes = MAX_NON_LFS; |
110 | * BB: May be it is better to do simple copy before | ||
111 | * complex operation (mount), and in case of fail | ||
112 | * just exit instead of doing mount and attempting | ||
113 | * undo it if this copy fails?*/ | ||
114 | if (data) { | ||
115 | int len = strlen(data); | ||
116 | cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL); | ||
117 | if (cifs_sb->mountdata == NULL) { | ||
118 | bdi_destroy(&cifs_sb->bdi); | ||
119 | kfree(sb->s_fs_info); | ||
120 | sb->s_fs_info = NULL; | ||
121 | return -ENOMEM; | ||
122 | } | ||
123 | strncpy(cifs_sb->mountdata, data, len + 1); | ||
124 | cifs_sb->mountdata[len] = '\0'; | ||
125 | } | ||
126 | #endif | ||
127 | |||
128 | rc = cifs_mount(sb, cifs_sb, data, devname); | ||
129 | 123 | ||
130 | if (rc) { | 124 | /* BB FIXME fix time_gran to be larger for LANMAN sessions */ |
131 | if (!silent) | 125 | sb->s_time_gran = 100; |
132 | cERROR(1, "cifs_mount failed w/return code = %d", rc); | ||
133 | goto out_mount_failed; | ||
134 | } | ||
135 | 126 | ||
136 | sb->s_magic = CIFS_MAGIC_NUMBER; | 127 | sb->s_magic = CIFS_MAGIC_NUMBER; |
137 | sb->s_op = &cifs_super_ops; | 128 | sb->s_op = &cifs_super_ops; |
138 | sb->s_bdi = &cifs_sb->bdi; | 129 | sb->s_bdi = &cifs_sb->bdi; |
139 | /* if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512) | ||
140 | sb->s_blocksize = | ||
141 | cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */ | ||
142 | sb->s_blocksize = CIFS_MAX_MSGSIZE; | 130 | sb->s_blocksize = CIFS_MAX_MSGSIZE; |
143 | sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ | 131 | sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ |
144 | inode = cifs_root_iget(sb, ROOT_I); | 132 | inode = cifs_root_iget(sb); |
145 | 133 | ||
146 | if (IS_ERR(inode)) { | 134 | if (IS_ERR(inode)) { |
147 | rc = PTR_ERR(inode); | 135 | rc = PTR_ERR(inode); |
@@ -156,12 +144,18 @@ cifs_read_super(struct super_block *sb, void *data, | |||
156 | goto out_no_root; | 144 | goto out_no_root; |
157 | } | 145 | } |
158 | 146 | ||
159 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 147 | /* do that *after* d_alloc_root() - we want NULL ->d_op for root here */ |
148 | if (cifs_sb_master_tcon(cifs_sb)->nocase) | ||
149 | sb->s_d_op = &cifs_ci_dentry_ops; | ||
150 | else | ||
151 | sb->s_d_op = &cifs_dentry_ops; | ||
152 | |||
153 | #ifdef CIFS_NFSD_EXPORT | ||
160 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | 154 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { |
161 | cFYI(1, "export ops supported"); | 155 | cFYI(1, "export ops supported"); |
162 | sb->s_export_op = &cifs_export_ops; | 156 | sb->s_export_op = &cifs_export_ops; |
163 | } | 157 | } |
164 | #endif /* EXPERIMENTAL */ | 158 | #endif /* CIFS_NFSD_EXPORT */ |
165 | 159 | ||
166 | return 0; | 160 | return 0; |
167 | 161 | ||
@@ -170,53 +164,14 @@ out_no_root: | |||
170 | if (inode) | 164 | if (inode) |
171 | iput(inode); | 165 | iput(inode); |
172 | 166 | ||
173 | cifs_umount(sb, cifs_sb); | ||
174 | |||
175 | out_mount_failed: | ||
176 | if (cifs_sb) { | ||
177 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
178 | if (cifs_sb->mountdata) { | ||
179 | kfree(cifs_sb->mountdata); | ||
180 | cifs_sb->mountdata = NULL; | ||
181 | } | ||
182 | #endif | ||
183 | unload_nls(cifs_sb->local_nls); | ||
184 | bdi_destroy(&cifs_sb->bdi); | ||
185 | kfree(cifs_sb); | ||
186 | } | ||
187 | return rc; | 167 | return rc; |
188 | } | 168 | } |
189 | 169 | ||
190 | static void | 170 | static void cifs_kill_sb(struct super_block *sb) |
191 | cifs_put_super(struct super_block *sb) | ||
192 | { | 171 | { |
193 | int rc = 0; | 172 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
194 | struct cifs_sb_info *cifs_sb; | 173 | kill_anon_super(sb); |
195 | 174 | cifs_umount(cifs_sb); | |
196 | cFYI(1, "In cifs_put_super"); | ||
197 | cifs_sb = CIFS_SB(sb); | ||
198 | if (cifs_sb == NULL) { | ||
199 | cFYI(1, "Empty cifs superblock info passed to unmount"); | ||
200 | return; | ||
201 | } | ||
202 | |||
203 | lock_kernel(); | ||
204 | |||
205 | rc = cifs_umount(sb, cifs_sb); | ||
206 | if (rc) | ||
207 | cERROR(1, "cifs_umount failed with return code %d", rc); | ||
208 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
209 | if (cifs_sb->mountdata) { | ||
210 | kfree(cifs_sb->mountdata); | ||
211 | cifs_sb->mountdata = NULL; | ||
212 | } | ||
213 | #endif | ||
214 | |||
215 | unload_nls(cifs_sb->local_nls); | ||
216 | bdi_destroy(&cifs_sb->bdi); | ||
217 | kfree(cifs_sb); | ||
218 | |||
219 | unlock_kernel(); | ||
220 | } | 175 | } |
221 | 176 | ||
222 | static int | 177 | static int |
@@ -224,7 +179,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
224 | { | 179 | { |
225 | struct super_block *sb = dentry->d_sb; | 180 | struct super_block *sb = dentry->d_sb; |
226 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 181 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
227 | struct cifsTconInfo *tcon = cifs_sb->tcon; | 182 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); |
228 | int rc = -EOPNOTSUPP; | 183 | int rc = -EOPNOTSUPP; |
229 | int xid; | 184 | int xid; |
230 | 185 | ||
@@ -269,7 +224,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
269 | return 0; | 224 | return 0; |
270 | } | 225 | } |
271 | 226 | ||
272 | static int cifs_permission(struct inode *inode, int mask) | 227 | static int cifs_permission(struct inode *inode, int mask, unsigned int flags) |
273 | { | 228 | { |
274 | struct cifs_sb_info *cifs_sb; | 229 | struct cifs_sb_info *cifs_sb; |
275 | 230 | ||
@@ -284,7 +239,7 @@ static int cifs_permission(struct inode *inode, int mask) | |||
284 | on the client (above and beyond ACL on servers) for | 239 | on the client (above and beyond ACL on servers) for |
285 | servers which do not support setting and viewing mode bits, | 240 | servers which do not support setting and viewing mode bits, |
286 | so allowing client to check permissions is useful */ | 241 | so allowing client to check permissions is useful */ |
287 | return generic_permission(inode, mask, NULL); | 242 | return generic_permission(inode, mask, flags, NULL); |
288 | } | 243 | } |
289 | 244 | ||
290 | static struct kmem_cache *cifs_inode_cachep; | 245 | static struct kmem_cache *cifs_inode_cachep; |
@@ -304,16 +259,16 @@ cifs_alloc_inode(struct super_block *sb) | |||
304 | return NULL; | 259 | return NULL; |
305 | cifs_inode->cifsAttrs = 0x20; /* default */ | 260 | cifs_inode->cifsAttrs = 0x20; /* default */ |
306 | cifs_inode->time = 0; | 261 | cifs_inode->time = 0; |
307 | cifs_inode->write_behind_rc = 0; | ||
308 | /* Until the file is open and we have gotten oplock | 262 | /* Until the file is open and we have gotten oplock |
309 | info back from the server, can not assume caching of | 263 | info back from the server, can not assume caching of |
310 | file data or metadata */ | 264 | file data or metadata */ |
311 | cifs_inode->clientCanCacheRead = false; | 265 | cifs_set_oplock_level(cifs_inode, 0); |
312 | cifs_inode->clientCanCacheAll = false; | ||
313 | cifs_inode->delete_pending = false; | 266 | cifs_inode->delete_pending = false; |
314 | cifs_inode->invalid_mapping = false; | 267 | cifs_inode->invalid_mapping = false; |
315 | cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ | 268 | cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ |
316 | cifs_inode->server_eof = 0; | 269 | cifs_inode->server_eof = 0; |
270 | cifs_inode->uniqueid = 0; | ||
271 | cifs_inode->createtime = 0; | ||
317 | 272 | ||
318 | /* Can not set i_flags here - they get immediately overwritten | 273 | /* Can not set i_flags here - they get immediately overwritten |
319 | to zero by the VFS */ | 274 | to zero by the VFS */ |
@@ -322,10 +277,17 @@ cifs_alloc_inode(struct super_block *sb) | |||
322 | return &cifs_inode->vfs_inode; | 277 | return &cifs_inode->vfs_inode; |
323 | } | 278 | } |
324 | 279 | ||
280 | static void cifs_i_callback(struct rcu_head *head) | ||
281 | { | ||
282 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
283 | INIT_LIST_HEAD(&inode->i_dentry); | ||
284 | kmem_cache_free(cifs_inode_cachep, CIFS_I(inode)); | ||
285 | } | ||
286 | |||
325 | static void | 287 | static void |
326 | cifs_destroy_inode(struct inode *inode) | 288 | cifs_destroy_inode(struct inode *inode) |
327 | { | 289 | { |
328 | kmem_cache_free(cifs_inode_cachep, CIFS_I(inode)); | 290 | call_rcu(&inode->i_rcu, cifs_i_callback); |
329 | } | 291 | } |
330 | 292 | ||
331 | static void | 293 | static void |
@@ -339,24 +301,56 @@ cifs_evict_inode(struct inode *inode) | |||
339 | static void | 301 | static void |
340 | cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) | 302 | cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) |
341 | { | 303 | { |
304 | struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr; | ||
305 | struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr; | ||
306 | |||
342 | seq_printf(s, ",addr="); | 307 | seq_printf(s, ",addr="); |
343 | 308 | ||
344 | switch (server->addr.sockAddr.sin_family) { | 309 | switch (server->dstaddr.ss_family) { |
345 | case AF_INET: | 310 | case AF_INET: |
346 | seq_printf(s, "%pI4", &server->addr.sockAddr.sin_addr.s_addr); | 311 | seq_printf(s, "%pI4", &sa->sin_addr.s_addr); |
347 | break; | 312 | break; |
348 | case AF_INET6: | 313 | case AF_INET6: |
349 | seq_printf(s, "%pI6", | 314 | seq_printf(s, "%pI6", &sa6->sin6_addr.s6_addr); |
350 | &server->addr.sockAddr6.sin6_addr.s6_addr); | 315 | if (sa6->sin6_scope_id) |
351 | if (server->addr.sockAddr6.sin6_scope_id) | 316 | seq_printf(s, "%%%u", sa6->sin6_scope_id); |
352 | seq_printf(s, "%%%u", | ||
353 | server->addr.sockAddr6.sin6_scope_id); | ||
354 | break; | 317 | break; |
355 | default: | 318 | default: |
356 | seq_printf(s, "(unknown)"); | 319 | seq_printf(s, "(unknown)"); |
357 | } | 320 | } |
358 | } | 321 | } |
359 | 322 | ||
323 | static void | ||
324 | cifs_show_security(struct seq_file *s, struct TCP_Server_Info *server) | ||
325 | { | ||
326 | seq_printf(s, ",sec="); | ||
327 | |||
328 | switch (server->secType) { | ||
329 | case LANMAN: | ||
330 | seq_printf(s, "lanman"); | ||
331 | break; | ||
332 | case NTLMv2: | ||
333 | seq_printf(s, "ntlmv2"); | ||
334 | break; | ||
335 | case NTLM: | ||
336 | seq_printf(s, "ntlm"); | ||
337 | break; | ||
338 | case Kerberos: | ||
339 | seq_printf(s, "krb5"); | ||
340 | break; | ||
341 | case RawNTLMSSP: | ||
342 | seq_printf(s, "ntlmssp"); | ||
343 | break; | ||
344 | default: | ||
345 | /* shouldn't ever happen */ | ||
346 | seq_printf(s, "unknown"); | ||
347 | break; | ||
348 | } | ||
349 | |||
350 | if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
351 | seq_printf(s, "i"); | ||
352 | } | ||
353 | |||
360 | /* | 354 | /* |
361 | * cifs_show_options() is for displaying mount options in /proc/mounts. | 355 | * cifs_show_options() is for displaying mount options in /proc/mounts. |
362 | * Not all settable options are displayed but most of the important | 356 | * Not all settable options are displayed but most of the important |
@@ -366,14 +360,38 @@ static int | |||
366 | cifs_show_options(struct seq_file *s, struct vfsmount *m) | 360 | cifs_show_options(struct seq_file *s, struct vfsmount *m) |
367 | { | 361 | { |
368 | struct cifs_sb_info *cifs_sb = CIFS_SB(m->mnt_sb); | 362 | struct cifs_sb_info *cifs_sb = CIFS_SB(m->mnt_sb); |
369 | struct cifsTconInfo *tcon = cifs_sb->tcon; | 363 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); |
364 | struct sockaddr *srcaddr; | ||
365 | srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr; | ||
366 | |||
367 | cifs_show_security(s, tcon->ses->server); | ||
370 | 368 | ||
371 | seq_printf(s, ",unc=%s", tcon->treeName); | 369 | seq_printf(s, ",unc=%s", tcon->treeName); |
372 | if (tcon->ses->userName) | 370 | |
373 | seq_printf(s, ",username=%s", tcon->ses->userName); | 371 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) |
372 | seq_printf(s, ",multiuser"); | ||
373 | else if (tcon->ses->user_name) | ||
374 | seq_printf(s, ",username=%s", tcon->ses->user_name); | ||
375 | |||
374 | if (tcon->ses->domainName) | 376 | if (tcon->ses->domainName) |
375 | seq_printf(s, ",domain=%s", tcon->ses->domainName); | 377 | seq_printf(s, ",domain=%s", tcon->ses->domainName); |
376 | 378 | ||
379 | if (srcaddr->sa_family != AF_UNSPEC) { | ||
380 | struct sockaddr_in *saddr4; | ||
381 | struct sockaddr_in6 *saddr6; | ||
382 | saddr4 = (struct sockaddr_in *)srcaddr; | ||
383 | saddr6 = (struct sockaddr_in6 *)srcaddr; | ||
384 | if (srcaddr->sa_family == AF_INET6) | ||
385 | seq_printf(s, ",srcaddr=%pI6c", | ||
386 | &saddr6->sin6_addr); | ||
387 | else if (srcaddr->sa_family == AF_INET) | ||
388 | seq_printf(s, ",srcaddr=%pI4", | ||
389 | &saddr4->sin_addr.s_addr); | ||
390 | else | ||
391 | seq_printf(s, ",srcaddr=BAD-AF:%i", | ||
392 | (int)(srcaddr->sa_family)); | ||
393 | } | ||
394 | |||
377 | seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); | 395 | seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); |
378 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) | 396 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) |
379 | seq_printf(s, ",forceuid"); | 397 | seq_printf(s, ",forceuid"); |
@@ -398,14 +416,20 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) | |||
398 | seq_printf(s, ",nocase"); | 416 | seq_printf(s, ",nocase"); |
399 | if (tcon->retry) | 417 | if (tcon->retry) |
400 | seq_printf(s, ",hard"); | 418 | seq_printf(s, ",hard"); |
401 | if (cifs_sb->prepath) | 419 | if (tcon->unix_ext) |
402 | seq_printf(s, ",prepath=%s", cifs_sb->prepath); | 420 | seq_printf(s, ",unix"); |
421 | else | ||
422 | seq_printf(s, ",nounix"); | ||
403 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) | 423 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) |
404 | seq_printf(s, ",posixpaths"); | 424 | seq_printf(s, ",posixpaths"); |
405 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) | 425 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) |
406 | seq_printf(s, ",setuids"); | 426 | seq_printf(s, ",setuids"); |
407 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) | 427 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) |
408 | seq_printf(s, ",serverino"); | 428 | seq_printf(s, ",serverino"); |
429 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) | ||
430 | seq_printf(s, ",rwpidforward"); | ||
431 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) | ||
432 | seq_printf(s, ",forcemand"); | ||
409 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) | 433 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) |
410 | seq_printf(s, ",directio"); | 434 | seq_printf(s, ",directio"); |
411 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) | 435 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) |
@@ -422,9 +446,15 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) | |||
422 | seq_printf(s, ",dynperm"); | 446 | seq_printf(s, ",dynperm"); |
423 | if (m->mnt_sb->s_flags & MS_POSIXACL) | 447 | if (m->mnt_sb->s_flags & MS_POSIXACL) |
424 | seq_printf(s, ",acl"); | 448 | seq_printf(s, ",acl"); |
449 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) | ||
450 | seq_printf(s, ",mfsymlinks"); | ||
451 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) | ||
452 | seq_printf(s, ",fsc"); | ||
425 | 453 | ||
426 | seq_printf(s, ",rsize=%d", cifs_sb->rsize); | 454 | seq_printf(s, ",rsize=%d", cifs_sb->rsize); |
427 | seq_printf(s, ",wsize=%d", cifs_sb->wsize); | 455 | seq_printf(s, ",wsize=%d", cifs_sb->wsize); |
456 | /* convert actimeo and display it in seconds */ | ||
457 | seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ); | ||
428 | 458 | ||
429 | return 0; | 459 | return 0; |
430 | } | 460 | } |
@@ -432,25 +462,23 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) | |||
432 | static void cifs_umount_begin(struct super_block *sb) | 462 | static void cifs_umount_begin(struct super_block *sb) |
433 | { | 463 | { |
434 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 464 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
435 | struct cifsTconInfo *tcon; | 465 | struct cifs_tcon *tcon; |
436 | 466 | ||
437 | if (cifs_sb == NULL) | 467 | if (cifs_sb == NULL) |
438 | return; | 468 | return; |
439 | 469 | ||
440 | tcon = cifs_sb->tcon; | 470 | tcon = cifs_sb_master_tcon(cifs_sb); |
441 | if (tcon == NULL) | ||
442 | return; | ||
443 | 471 | ||
444 | read_lock(&cifs_tcp_ses_lock); | 472 | spin_lock(&cifs_tcp_ses_lock); |
445 | if ((tcon->tc_count > 1) || (tcon->tidStatus == CifsExiting)) { | 473 | if ((tcon->tc_count > 1) || (tcon->tidStatus == CifsExiting)) { |
446 | /* we have other mounts to same share or we have | 474 | /* we have other mounts to same share or we have |
447 | already tried to force umount this and woken up | 475 | already tried to force umount this and woken up |
448 | all waiting network requests, nothing to do */ | 476 | all waiting network requests, nothing to do */ |
449 | read_unlock(&cifs_tcp_ses_lock); | 477 | spin_unlock(&cifs_tcp_ses_lock); |
450 | return; | 478 | return; |
451 | } else if (tcon->tc_count == 1) | 479 | } else if (tcon->tc_count == 1) |
452 | tcon->tidStatus = CifsExiting; | 480 | tcon->tidStatus = CifsExiting; |
453 | read_unlock(&cifs_tcp_ses_lock); | 481 | spin_unlock(&cifs_tcp_ses_lock); |
454 | 482 | ||
455 | /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */ | 483 | /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */ |
456 | /* cancel_notify_requests(tcon); */ | 484 | /* cancel_notify_requests(tcon); */ |
@@ -491,7 +519,6 @@ static int cifs_drop_inode(struct inode *inode) | |||
491 | } | 519 | } |
492 | 520 | ||
493 | static const struct super_operations cifs_super_ops = { | 521 | static const struct super_operations cifs_super_ops = { |
494 | .put_super = cifs_put_super, | ||
495 | .statfs = cifs_statfs, | 522 | .statfs = cifs_statfs, |
496 | .alloc_inode = cifs_alloc_inode, | 523 | .alloc_inode = cifs_alloc_inode, |
497 | .destroy_inode = cifs_destroy_inode, | 524 | .destroy_inode = cifs_destroy_inode, |
@@ -509,28 +536,151 @@ static const struct super_operations cifs_super_ops = { | |||
509 | #endif | 536 | #endif |
510 | }; | 537 | }; |
511 | 538 | ||
512 | static int | 539 | /* |
513 | cifs_get_sb(struct file_system_type *fs_type, | 540 | * Get root dentry from superblock according to prefix path mount option. |
514 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 541 | * Return dentry with refcount + 1 on success and NULL otherwise. |
542 | */ | ||
543 | static struct dentry * | ||
544 | cifs_get_root(struct smb_vol *vol, struct super_block *sb) | ||
545 | { | ||
546 | struct dentry *dentry; | ||
547 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | ||
548 | char *full_path = NULL; | ||
549 | char *s, *p; | ||
550 | char sep; | ||
551 | int xid; | ||
552 | |||
553 | full_path = cifs_build_path_to_root(vol, cifs_sb, | ||
554 | cifs_sb_master_tcon(cifs_sb)); | ||
555 | if (full_path == NULL) | ||
556 | return ERR_PTR(-ENOMEM); | ||
557 | |||
558 | cFYI(1, "Get root dentry for %s", full_path); | ||
559 | |||
560 | xid = GetXid(); | ||
561 | sep = CIFS_DIR_SEP(cifs_sb); | ||
562 | dentry = dget(sb->s_root); | ||
563 | p = s = full_path; | ||
564 | |||
565 | do { | ||
566 | struct inode *dir = dentry->d_inode; | ||
567 | struct dentry *child; | ||
568 | |||
569 | /* skip separators */ | ||
570 | while (*s == sep) | ||
571 | s++; | ||
572 | if (!*s) | ||
573 | break; | ||
574 | p = s++; | ||
575 | /* next separator */ | ||
576 | while (*s && *s != sep) | ||
577 | s++; | ||
578 | |||
579 | mutex_lock(&dir->i_mutex); | ||
580 | child = lookup_one_len(p, dentry, s - p); | ||
581 | mutex_unlock(&dir->i_mutex); | ||
582 | dput(dentry); | ||
583 | dentry = child; | ||
584 | } while (!IS_ERR(dentry)); | ||
585 | _FreeXid(xid); | ||
586 | kfree(full_path); | ||
587 | return dentry; | ||
588 | } | ||
589 | |||
590 | static int cifs_set_super(struct super_block *sb, void *data) | ||
591 | { | ||
592 | struct cifs_mnt_data *mnt_data = data; | ||
593 | sb->s_fs_info = mnt_data->cifs_sb; | ||
594 | return set_anon_super(sb, NULL); | ||
595 | } | ||
596 | |||
597 | static struct dentry * | ||
598 | cifs_do_mount(struct file_system_type *fs_type, | ||
599 | int flags, const char *dev_name, void *data) | ||
515 | { | 600 | { |
516 | int rc; | 601 | int rc; |
517 | struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL); | 602 | struct super_block *sb; |
603 | struct cifs_sb_info *cifs_sb; | ||
604 | struct smb_vol *volume_info; | ||
605 | struct cifs_mnt_data mnt_data; | ||
606 | struct dentry *root; | ||
518 | 607 | ||
519 | cFYI(1, "Devname: %s flags: %d ", dev_name, flags); | 608 | cFYI(1, "Devname: %s flags: %d ", dev_name, flags); |
520 | 609 | ||
521 | if (IS_ERR(sb)) | 610 | volume_info = cifs_get_volume_info((char *)data, dev_name); |
522 | return PTR_ERR(sb); | 611 | if (IS_ERR(volume_info)) |
612 | return ERR_CAST(volume_info); | ||
523 | 613 | ||
524 | sb->s_flags = flags; | 614 | cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); |
615 | if (cifs_sb == NULL) { | ||
616 | root = ERR_PTR(-ENOMEM); | ||
617 | goto out_nls; | ||
618 | } | ||
619 | |||
620 | cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); | ||
621 | if (cifs_sb->mountdata == NULL) { | ||
622 | root = ERR_PTR(-ENOMEM); | ||
623 | goto out_cifs_sb; | ||
624 | } | ||
525 | 625 | ||
526 | rc = cifs_read_super(sb, data, dev_name, flags & MS_SILENT ? 1 : 0); | 626 | cifs_setup_cifs_sb(volume_info, cifs_sb); |
627 | |||
628 | rc = cifs_mount(cifs_sb, volume_info); | ||
527 | if (rc) { | 629 | if (rc) { |
528 | deactivate_locked_super(sb); | 630 | if (!(flags & MS_SILENT)) |
529 | return rc; | 631 | cERROR(1, "cifs_mount failed w/return code = %d", rc); |
632 | root = ERR_PTR(rc); | ||
633 | goto out_mountdata; | ||
530 | } | 634 | } |
531 | sb->s_flags |= MS_ACTIVE; | 635 | |
532 | simple_set_mnt(mnt, sb); | 636 | mnt_data.vol = volume_info; |
533 | return 0; | 637 | mnt_data.cifs_sb = cifs_sb; |
638 | mnt_data.flags = flags; | ||
639 | |||
640 | sb = sget(fs_type, cifs_match_super, cifs_set_super, &mnt_data); | ||
641 | if (IS_ERR(sb)) { | ||
642 | root = ERR_CAST(sb); | ||
643 | cifs_umount(cifs_sb); | ||
644 | goto out; | ||
645 | } | ||
646 | |||
647 | if (sb->s_root) { | ||
648 | cFYI(1, "Use existing superblock"); | ||
649 | cifs_umount(cifs_sb); | ||
650 | } else { | ||
651 | sb->s_flags = flags; | ||
652 | /* BB should we make this contingent on mount parm? */ | ||
653 | sb->s_flags |= MS_NODIRATIME | MS_NOATIME; | ||
654 | |||
655 | rc = cifs_read_super(sb); | ||
656 | if (rc) { | ||
657 | root = ERR_PTR(rc); | ||
658 | goto out_super; | ||
659 | } | ||
660 | |||
661 | sb->s_flags |= MS_ACTIVE; | ||
662 | } | ||
663 | |||
664 | root = cifs_get_root(volume_info, sb); | ||
665 | if (IS_ERR(root)) | ||
666 | goto out_super; | ||
667 | |||
668 | cFYI(1, "dentry root is: %p", root); | ||
669 | goto out; | ||
670 | |||
671 | out_super: | ||
672 | deactivate_locked_super(sb); | ||
673 | out: | ||
674 | cifs_cleanup_volume_info(volume_info); | ||
675 | return root; | ||
676 | |||
677 | out_mountdata: | ||
678 | kfree(cifs_sb->mountdata); | ||
679 | out_cifs_sb: | ||
680 | kfree(cifs_sb); | ||
681 | out_nls: | ||
682 | unload_nls(volume_info->local_nls); | ||
683 | goto out; | ||
534 | } | 684 | } |
535 | 685 | ||
536 | static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | 686 | static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, |
@@ -538,10 +688,17 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
538 | { | 688 | { |
539 | struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; | 689 | struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; |
540 | ssize_t written; | 690 | ssize_t written; |
691 | int rc; | ||
541 | 692 | ||
542 | written = generic_file_aio_write(iocb, iov, nr_segs, pos); | 693 | written = generic_file_aio_write(iocb, iov, nr_segs, pos); |
543 | if (!CIFS_I(inode)->clientCanCacheAll) | 694 | |
544 | filemap_fdatawrite(inode->i_mapping); | 695 | if (CIFS_I(inode)->clientCanCacheAll) |
696 | return written; | ||
697 | |||
698 | rc = filemap_fdatawrite(inode->i_mapping); | ||
699 | if (rc) | ||
700 | cFYI(1, "cifs_file_aio_write: %d rc on %p inode", rc, inode); | ||
701 | |||
545 | return written; | 702 | return written; |
546 | } | 703 | } |
547 | 704 | ||
@@ -549,25 +706,41 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) | |||
549 | { | 706 | { |
550 | /* origin == SEEK_END => we must revalidate the cached file length */ | 707 | /* origin == SEEK_END => we must revalidate the cached file length */ |
551 | if (origin == SEEK_END) { | 708 | if (origin == SEEK_END) { |
552 | int retval; | 709 | int rc; |
553 | 710 | struct inode *inode = file->f_path.dentry->d_inode; | |
554 | /* some applications poll for the file length in this strange | 711 | |
555 | way so we must seek to end on non-oplocked files by | 712 | /* |
556 | setting the revalidate time to zero */ | 713 | * We need to be sure that all dirty pages are written and the |
557 | CIFS_I(file->f_path.dentry->d_inode)->time = 0; | 714 | * server has the newest file length. |
558 | 715 | */ | |
559 | retval = cifs_revalidate_file(file); | 716 | if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping && |
560 | if (retval < 0) | 717 | inode->i_mapping->nrpages != 0) { |
561 | return (loff_t)retval; | 718 | rc = filemap_fdatawait(inode->i_mapping); |
719 | if (rc) { | ||
720 | mapping_set_error(inode->i_mapping, rc); | ||
721 | return rc; | ||
722 | } | ||
723 | } | ||
724 | /* | ||
725 | * Some applications poll for the file length in this strange | ||
726 | * way so we must seek to end on non-oplocked files by | ||
727 | * setting the revalidate time to zero. | ||
728 | */ | ||
729 | CIFS_I(inode)->time = 0; | ||
730 | |||
731 | rc = cifs_revalidate_file_attr(file); | ||
732 | if (rc < 0) | ||
733 | return (loff_t)rc; | ||
562 | } | 734 | } |
563 | return generic_file_llseek_unlocked(file, offset, origin); | 735 | return generic_file_llseek_unlocked(file, offset, origin); |
564 | } | 736 | } |
565 | 737 | ||
566 | static int cifs_setlease(struct file *file, long arg, struct file_lock **lease) | 738 | static int cifs_setlease(struct file *file, long arg, struct file_lock **lease) |
567 | { | 739 | { |
568 | /* note that this is called by vfs setlease with the BKL held | 740 | /* note that this is called by vfs setlease with lock_flocks held |
569 | although I doubt that BKL is needed here in cifs */ | 741 | to protect *lease from going away */ |
570 | struct inode *inode = file->f_path.dentry->d_inode; | 742 | struct inode *inode = file->f_path.dentry->d_inode; |
743 | struct cifsFileInfo *cfile = file->private_data; | ||
571 | 744 | ||
572 | if (!(S_ISREG(inode->i_mode))) | 745 | if (!(S_ISREG(inode->i_mode))) |
573 | return -EINVAL; | 746 | return -EINVAL; |
@@ -578,8 +751,8 @@ static int cifs_setlease(struct file *file, long arg, struct file_lock **lease) | |||
578 | ((arg == F_WRLCK) && | 751 | ((arg == F_WRLCK) && |
579 | (CIFS_I(inode)->clientCanCacheAll))) | 752 | (CIFS_I(inode)->clientCanCacheAll))) |
580 | return generic_setlease(file, arg, lease); | 753 | return generic_setlease(file, arg, lease); |
581 | else if (CIFS_SB(inode->i_sb)->tcon->local_lease && | 754 | else if (tlink_tcon(cfile->tlink)->local_lease && |
582 | !CIFS_I(inode)->clientCanCacheRead) | 755 | !CIFS_I(inode)->clientCanCacheRead) |
583 | /* If the server claims to support oplock on this | 756 | /* If the server claims to support oplock on this |
584 | file, then we still need to check oplock even | 757 | file, then we still need to check oplock even |
585 | if the local_lease mount option is set, but there | 758 | if the local_lease mount option is set, but there |
@@ -595,8 +768,8 @@ static int cifs_setlease(struct file *file, long arg, struct file_lock **lease) | |||
595 | struct file_system_type cifs_fs_type = { | 768 | struct file_system_type cifs_fs_type = { |
596 | .owner = THIS_MODULE, | 769 | .owner = THIS_MODULE, |
597 | .name = "cifs", | 770 | .name = "cifs", |
598 | .get_sb = cifs_get_sb, | 771 | .mount = cifs_do_mount, |
599 | .kill_sb = kill_anon_super, | 772 | .kill_sb = cifs_kill_sb, |
600 | /* .fs_flags */ | 773 | /* .fs_flags */ |
601 | }; | 774 | }; |
602 | const struct inode_operations cifs_dir_inode_ops = { | 775 | const struct inode_operations cifs_dir_inode_ops = { |
@@ -670,11 +843,31 @@ const struct file_operations cifs_file_ops = { | |||
670 | .setlease = cifs_setlease, | 843 | .setlease = cifs_setlease, |
671 | }; | 844 | }; |
672 | 845 | ||
846 | const struct file_operations cifs_file_strict_ops = { | ||
847 | .read = do_sync_read, | ||
848 | .write = do_sync_write, | ||
849 | .aio_read = cifs_strict_readv, | ||
850 | .aio_write = cifs_strict_writev, | ||
851 | .open = cifs_open, | ||
852 | .release = cifs_close, | ||
853 | .lock = cifs_lock, | ||
854 | .fsync = cifs_strict_fsync, | ||
855 | .flush = cifs_flush, | ||
856 | .mmap = cifs_file_strict_mmap, | ||
857 | .splice_read = generic_file_splice_read, | ||
858 | .llseek = cifs_llseek, | ||
859 | #ifdef CONFIG_CIFS_POSIX | ||
860 | .unlocked_ioctl = cifs_ioctl, | ||
861 | #endif /* CONFIG_CIFS_POSIX */ | ||
862 | .setlease = cifs_setlease, | ||
863 | }; | ||
864 | |||
673 | const struct file_operations cifs_file_direct_ops = { | 865 | const struct file_operations cifs_file_direct_ops = { |
674 | /* no aio, no readv - | 866 | /* BB reevaluate whether they can be done with directio, no cache */ |
675 | BB reevaluate whether they can be done with directio, no cache */ | 867 | .read = do_sync_read, |
676 | .read = cifs_user_read, | 868 | .write = do_sync_write, |
677 | .write = cifs_user_write, | 869 | .aio_read = cifs_user_readv, |
870 | .aio_write = cifs_user_writev, | ||
678 | .open = cifs_open, | 871 | .open = cifs_open, |
679 | .release = cifs_close, | 872 | .release = cifs_close, |
680 | .lock = cifs_lock, | 873 | .lock = cifs_lock, |
@@ -688,6 +881,7 @@ const struct file_operations cifs_file_direct_ops = { | |||
688 | .llseek = cifs_llseek, | 881 | .llseek = cifs_llseek, |
689 | .setlease = cifs_setlease, | 882 | .setlease = cifs_setlease, |
690 | }; | 883 | }; |
884 | |||
691 | const struct file_operations cifs_file_nobrl_ops = { | 885 | const struct file_operations cifs_file_nobrl_ops = { |
692 | .read = do_sync_read, | 886 | .read = do_sync_read, |
693 | .write = do_sync_write, | 887 | .write = do_sync_write, |
@@ -706,11 +900,30 @@ const struct file_operations cifs_file_nobrl_ops = { | |||
706 | .setlease = cifs_setlease, | 900 | .setlease = cifs_setlease, |
707 | }; | 901 | }; |
708 | 902 | ||
903 | const struct file_operations cifs_file_strict_nobrl_ops = { | ||
904 | .read = do_sync_read, | ||
905 | .write = do_sync_write, | ||
906 | .aio_read = cifs_strict_readv, | ||
907 | .aio_write = cifs_strict_writev, | ||
908 | .open = cifs_open, | ||
909 | .release = cifs_close, | ||
910 | .fsync = cifs_strict_fsync, | ||
911 | .flush = cifs_flush, | ||
912 | .mmap = cifs_file_strict_mmap, | ||
913 | .splice_read = generic_file_splice_read, | ||
914 | .llseek = cifs_llseek, | ||
915 | #ifdef CONFIG_CIFS_POSIX | ||
916 | .unlocked_ioctl = cifs_ioctl, | ||
917 | #endif /* CONFIG_CIFS_POSIX */ | ||
918 | .setlease = cifs_setlease, | ||
919 | }; | ||
920 | |||
709 | const struct file_operations cifs_file_direct_nobrl_ops = { | 921 | const struct file_operations cifs_file_direct_nobrl_ops = { |
710 | /* no mmap, no aio, no readv - | 922 | /* BB reevaluate whether they can be done with directio, no cache */ |
711 | BB reevaluate whether they can be done with directio, no cache */ | 923 | .read = do_sync_read, |
712 | .read = cifs_user_read, | 924 | .write = do_sync_write, |
713 | .write = cifs_user_write, | 925 | .aio_read = cifs_user_readv, |
926 | .aio_write = cifs_user_writev, | ||
714 | .open = cifs_open, | 927 | .open = cifs_open, |
715 | .release = cifs_close, | 928 | .release = cifs_close, |
716 | .fsync = cifs_fsync, | 929 | .fsync = cifs_fsync, |
@@ -873,10 +1086,10 @@ init_cifs(void) | |||
873 | int rc = 0; | 1086 | int rc = 0; |
874 | cifs_proc_init(); | 1087 | cifs_proc_init(); |
875 | INIT_LIST_HEAD(&cifs_tcp_ses_list); | 1088 | INIT_LIST_HEAD(&cifs_tcp_ses_list); |
876 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 1089 | #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */ |
877 | INIT_LIST_HEAD(&GlobalDnotifyReqList); | 1090 | INIT_LIST_HEAD(&GlobalDnotifyReqList); |
878 | INIT_LIST_HEAD(&GlobalDnotifyRsp_Q); | 1091 | INIT_LIST_HEAD(&GlobalDnotifyRsp_Q); |
879 | #endif | 1092 | #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */ |
880 | /* | 1093 | /* |
881 | * Initialize Global counters | 1094 | * Initialize Global counters |
882 | */ | 1095 | */ |
@@ -897,9 +1110,8 @@ init_cifs(void) | |||
897 | GlobalCurrentXid = 0; | 1110 | GlobalCurrentXid = 0; |
898 | GlobalTotalActiveXid = 0; | 1111 | GlobalTotalActiveXid = 0; |
899 | GlobalMaxActiveXid = 0; | 1112 | GlobalMaxActiveXid = 0; |
900 | memset(Local_System_Name, 0, 15); | 1113 | spin_lock_init(&cifs_tcp_ses_lock); |
901 | rwlock_init(&GlobalSMBSeslock); | 1114 | spin_lock_init(&cifs_file_list_lock); |
902 | rwlock_init(&cifs_tcp_ses_lock); | ||
903 | spin_lock_init(&GlobalMid_Lock); | 1115 | spin_lock_init(&GlobalMid_Lock); |
904 | 1116 | ||
905 | if (cifs_max_pending < 2) { | 1117 | if (cifs_max_pending < 2) { |
@@ -912,11 +1124,11 @@ init_cifs(void) | |||
912 | 1124 | ||
913 | rc = cifs_fscache_register(); | 1125 | rc = cifs_fscache_register(); |
914 | if (rc) | 1126 | if (rc) |
915 | goto out; | 1127 | goto out_clean_proc; |
916 | 1128 | ||
917 | rc = cifs_init_inodecache(); | 1129 | rc = cifs_init_inodecache(); |
918 | if (rc) | 1130 | if (rc) |
919 | goto out_clean_proc; | 1131 | goto out_unreg_fscache; |
920 | 1132 | ||
921 | rc = cifs_init_mids(); | 1133 | rc = cifs_init_mids(); |
922 | if (rc) | 1134 | if (rc) |
@@ -926,31 +1138,42 @@ init_cifs(void) | |||
926 | if (rc) | 1138 | if (rc) |
927 | goto out_destroy_mids; | 1139 | goto out_destroy_mids; |
928 | 1140 | ||
929 | rc = register_filesystem(&cifs_fs_type); | ||
930 | if (rc) | ||
931 | goto out_destroy_request_bufs; | ||
932 | #ifdef CONFIG_CIFS_UPCALL | 1141 | #ifdef CONFIG_CIFS_UPCALL |
933 | rc = register_key_type(&cifs_spnego_key_type); | 1142 | rc = register_key_type(&cifs_spnego_key_type); |
934 | if (rc) | 1143 | if (rc) |
935 | goto out_unregister_filesystem; | 1144 | goto out_destroy_request_bufs; |
936 | #endif | 1145 | #endif /* CONFIG_CIFS_UPCALL */ |
1146 | |||
1147 | #ifdef CONFIG_CIFS_ACL | ||
1148 | rc = init_cifs_idmap(); | ||
1149 | if (rc) | ||
1150 | goto out_register_key_type; | ||
1151 | #endif /* CONFIG_CIFS_ACL */ | ||
1152 | |||
1153 | rc = register_filesystem(&cifs_fs_type); | ||
1154 | if (rc) | ||
1155 | goto out_init_cifs_idmap; | ||
937 | 1156 | ||
938 | return 0; | 1157 | return 0; |
939 | 1158 | ||
1159 | out_init_cifs_idmap: | ||
1160 | #ifdef CONFIG_CIFS_ACL | ||
1161 | exit_cifs_idmap(); | ||
1162 | out_register_key_type: | ||
1163 | #endif | ||
940 | #ifdef CONFIG_CIFS_UPCALL | 1164 | #ifdef CONFIG_CIFS_UPCALL |
941 | out_unregister_filesystem: | 1165 | unregister_key_type(&cifs_spnego_key_type); |
942 | unregister_filesystem(&cifs_fs_type); | 1166 | out_destroy_request_bufs: |
943 | #endif | 1167 | #endif |
944 | out_destroy_request_bufs: | ||
945 | cifs_destroy_request_bufs(); | 1168 | cifs_destroy_request_bufs(); |
946 | out_destroy_mids: | 1169 | out_destroy_mids: |
947 | cifs_destroy_mids(); | 1170 | cifs_destroy_mids(); |
948 | out_destroy_inodecache: | 1171 | out_destroy_inodecache: |
949 | cifs_destroy_inodecache(); | 1172 | cifs_destroy_inodecache(); |
950 | out_clean_proc: | 1173 | out_unreg_fscache: |
951 | cifs_proc_clean(); | ||
952 | cifs_fscache_unregister(); | 1174 | cifs_fscache_unregister(); |
953 | out: | 1175 | out_clean_proc: |
1176 | cifs_proc_clean(); | ||
954 | return rc; | 1177 | return rc; |
955 | } | 1178 | } |
956 | 1179 | ||
@@ -963,6 +1186,10 @@ exit_cifs(void) | |||
963 | #ifdef CONFIG_CIFS_DFS_UPCALL | 1186 | #ifdef CONFIG_CIFS_DFS_UPCALL |
964 | cifs_dfs_release_automount_timer(); | 1187 | cifs_dfs_release_automount_timer(); |
965 | #endif | 1188 | #endif |
1189 | #ifdef CONFIG_CIFS_ACL | ||
1190 | cifs_destroy_idmaptrees(); | ||
1191 | exit_cifs_idmap(); | ||
1192 | #endif | ||
966 | #ifdef CONFIG_CIFS_UPCALL | 1193 | #ifdef CONFIG_CIFS_UPCALL |
967 | unregister_key_type(&cifs_spnego_key_type); | 1194 | unregister_key_type(&cifs_spnego_key_type); |
968 | #endif | 1195 | #endif |