blob: 2af14d4577a7ed1e4d499ae5e443f02f3ae14fdb [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/cifsfs.c
3 *
Steve French2b280fa2008-05-17 03:12:45 +00004 * Copyright (C) International Business Machines Corp., 2002,2008
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * Common Internet FileSystem (CIFS) client
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24/* Note that BB means BUGBUG (ie something to fix eventually) */
25
26#include <linux/module.h>
27#include <linux/fs.h>
28#include <linux/mount.h>
29#include <linux/slab.h>
30#include <linux/init.h>
31#include <linux/list.h>
32#include <linux/seq_file.h>
33#include <linux/vfs.h>
34#include <linux/mempool.h>
Steve French6ab16d22005-11-29 20:55:11 -080035#include <linux/delay.h>
Steve French45af7a02006-04-21 22:52:25 +000036#include <linux/kthread.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080037#include <linux/freezer.h>
Ben Greear3eb9a882010-09-01 17:06:02 -070038#include <net/ipv6.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include "cifsfs.h"
40#include "cifspdu.h"
41#define DECLARE_GLOBALS_HERE
42#include "cifsglob.h"
43#include "cifsproto.h"
44#include "cifs_debug.h"
45#include "cifs_fs_sb.h"
46#include <linux/mm.h>
Jeff Layton84a15b92007-11-03 05:02:24 +000047#include <linux/key-type.h>
Jeff Laytone5459372007-11-03 05:11:06 +000048#include "cifs_spnego.h"
Suresh Jayaramanf579cf32010-07-05 18:11:50 +053049#include "fscache.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
51
Linus Torvalds1da177e2005-04-16 15:20:36 -070052int cifsFYI = 0;
53int cifsERROR = 1;
54int traceSMB = 0;
55unsigned int oplockEnabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -070056unsigned int linuxExtEnabled = 1;
57unsigned int lookupCacheEnabled = 1;
58unsigned int multiuser_mount = 0;
Jeff Layton04912d62010-04-24 07:57:45 -040059unsigned int global_secflags = CIFSSEC_DEF;
Steve French39798772006-05-31 22:40:51 +000060/* unsigned int ntlmv2_support = 0; */
Linus Torvalds1da177e2005-04-16 15:20:36 -070061unsigned int sign_CIFS_PDUs = 1;
Josef 'Jeff' Sipekee9b6d62007-02-12 00:55:41 -080062static const struct super_operations cifs_super_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -070063unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
64module_param(CIFSMaxBufSize, int, 0);
Steve French63135e02007-07-17 17:34:02 +000065MODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header). "
66 "Default: 16384 Range: 8192 to 130048");
Linus Torvalds1da177e2005-04-16 15:20:36 -070067unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
68module_param(cifs_min_rcv, int, 0);
Steve French63135e02007-07-17 17:34:02 +000069MODULE_PARM_DESC(cifs_min_rcv, "Network buffers in pool. Default: 4 Range: "
70 "1 to 64");
Linus Torvalds1da177e2005-04-16 15:20:36 -070071unsigned int cifs_min_small = 30;
72module_param(cifs_min_small, int, 0);
Steve French63135e02007-07-17 17:34:02 +000073MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 "
74 "Range: 2 to 256");
Linus Torvalds1da177e2005-04-16 15:20:36 -070075unsigned int cifs_max_pending = CIFS_MAX_REQ;
76module_param(cifs_max_pending, int, 0);
Steve French63135e02007-07-17 17:34:02 +000077MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. "
78 "Default: 50 Range: 2 to 256");
Steve Frenchfda35942011-01-20 18:06:34 +000079unsigned short echo_retries = 5;
80module_param(echo_retries, ushort, 0644);
81MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and "
82 "reconnecting server. Default: 5. 0 means "
83 "never reconnect.");
Linus Torvalds1da177e2005-04-16 15:20:36 -070084extern mempool_t *cifs_sm_req_poolp;
85extern mempool_t *cifs_req_poolp;
86extern mempool_t *cifs_mid_poolp;
87
Jeff Laytond7c86ff2010-10-11 15:07:19 -040088void
89cifs_sb_active(struct super_block *sb)
90{
91 struct cifs_sb_info *server = CIFS_SB(sb);
92
93 if (atomic_inc_return(&server->active) == 1)
94 atomic_inc(&sb->s_active);
95}
96
97void
98cifs_sb_deactive(struct super_block *sb)
99{
100 struct cifs_sb_info *server = CIFS_SB(sb);
101
102 if (atomic_dec_and_test(&server->active))
103 deactivate_super(sb);
104}
105
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106static int
Pavel Shilovskyb2e5cd32011-05-25 13:35:34 +0400107cifs_read_super(struct super_block *sb, struct smb_vol *volume_info,
108 const char *devname, int silent)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109{
110 struct inode *inode;
Pavel Shilovskyb2e5cd32011-05-25 13:35:34 +0400111 struct cifs_sb_info *cifs_sb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 int rc = 0;
Steve French50c2f752007-07-13 00:33:32 +0000113
Pavel Shilovskyb2e5cd32011-05-25 13:35:34 +0400114 cifs_sb = CIFS_SB(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115
Al Viro2c6292a2011-06-17 09:05:48 -0400116 rc = cifs_mount(cifs_sb, volume_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117
118 if (rc) {
119 if (!silent)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000120 cERROR(1, "cifs_mount failed w/return code = %d", rc);
Al Virodd854462011-06-17 08:24:42 -0400121 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 }
123
Al Viro2c6292a2011-06-17 09:05:48 -0400124 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL)
125 sb->s_flags |= MS_POSIXACL;
126
127 if (cifs_sb_master_tcon(cifs_sb)->ses->capabilities & CAP_LARGE_FILES)
128 sb->s_maxbytes = MAX_LFS_FILESIZE;
129 else
130 sb->s_maxbytes = MAX_NON_LFS;
131
132 /* BB FIXME fix time_gran to be larger for LANMAN sessions */
133 sb->s_time_gran = 100;
134
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 sb->s_magic = CIFS_MAGIC_NUMBER;
136 sb->s_op = &cifs_super_ops;
Jens Axboe8044f7f2010-04-22 12:09:48 +0200137 sb->s_bdi = &cifs_sb->bdi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 sb->s_blocksize = CIFS_MAX_MSGSIZE;
139 sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -0600140 inode = cifs_root_iget(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141
David Howellsce634ab2008-02-07 00:15:33 -0800142 if (IS_ERR(inode)) {
143 rc = PTR_ERR(inode);
144 inode = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 goto out_no_root;
146 }
147
148 sb->s_root = d_alloc_root(inode);
149
150 if (!sb->s_root) {
151 rc = -ENOMEM;
152 goto out_no_root;
153 }
Steve French50c2f752007-07-13 00:33:32 +0000154
Al Viro1c929cf2010-12-18 11:43:51 -0500155 /* do that *after* d_alloc_root() - we want NULL ->d_op for root here */
156 if (cifs_sb_master_tcon(cifs_sb)->nocase)
157 sb->s_d_op = &cifs_ci_dentry_ops;
158 else
159 sb->s_d_op = &cifs_dentry_ops;
160
Shirish Pargaonkar25720872011-02-25 10:48:55 -0600161#ifdef CIFS_NFSD_EXPORT
Steve French7521a3c2007-07-11 18:30:34 +0000162 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000163 cFYI(1, "export ops supported");
Steve French7521a3c2007-07-11 18:30:34 +0000164 sb->s_export_op = &cifs_export_ops;
165 }
Shirish Pargaonkar25720872011-02-25 10:48:55 -0600166#endif /* CIFS_NFSD_EXPORT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167
168 return 0;
169
170out_no_root:
Joe Perchesb6b38f72010-04-21 03:50:45 +0000171 cERROR(1, "cifs_read_super: get root inode failed");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 if (inode)
173 iput(inode);
Steve French54b46022008-08-11 22:31:40 +0000174
Al Viro2a9b9952011-06-17 09:27:16 -0400175 cifs_umount(cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 return rc;
177}
178
179static void
180cifs_put_super(struct super_block *sb)
181{
182 int rc = 0;
183 struct cifs_sb_info *cifs_sb;
184
Joe Perchesb6b38f72010-04-21 03:50:45 +0000185 cFYI(1, "In cifs_put_super");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 cifs_sb = CIFS_SB(sb);
Steve French4523cc32007-04-30 20:13:06 +0000187 if (cifs_sb == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000188 cFYI(1, "Empty cifs superblock info passed to unmount");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 return;
190 }
Christoph Hellwig6cfd0142009-05-05 15:40:36 +0200191
Al Viro2a9b9952011-06-17 09:27:16 -0400192 cifs_umount(cifs_sb);
Al Viro6d686172011-06-17 08:34:57 -0400193}
Igor Mammedove6ab1582008-01-11 01:49:48 +0000194
Al Viro6d686172011-06-17 08:34:57 -0400195static void cifs_kill_sb(struct super_block *sb)
196{
197 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
198 kill_anon_super(sb);
199 kfree(cifs_sb->mountdata);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 unload_nls(cifs_sb->local_nls);
201 kfree(cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202}
203
204static int
David Howells726c3342006-06-23 02:02:58 -0700205cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206{
David Howells726c3342006-06-23 02:02:58 -0700207 struct super_block *sb = dentry->d_sb;
Steve French39da9842008-04-28 04:04:34 +0000208 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French96daf2b2011-05-27 04:34:02 +0000209 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Steve Frenchc81156d2005-04-28 22:41:07 -0700210 int rc = -EOPNOTSUPP;
Steve French39da9842008-04-28 04:04:34 +0000211 int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212
213 xid = GetXid();
214
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 buf->f_type = CIFS_MAGIC_NUMBER;
216
Steve French39da9842008-04-28 04:04:34 +0000217 /*
218 * PATH_MAX may be too long - it would presumably be total path,
219 * but note that some servers (includinng Samba 3) have a shorter
220 * maximum path.
221 *
222 * Instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO.
223 */
224 buf->f_namelen = PATH_MAX;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 buf->f_files = 0; /* undefined */
226 buf->f_ffree = 0; /* unlimited */
227
Steve French39da9842008-04-28 04:04:34 +0000228 /*
229 * We could add a second check for a QFS Unix capability bit
230 */
231 if ((tcon->ses->capabilities & CAP_UNIX) &&
232 (CIFS_POSIX_EXTENSIONS & le64_to_cpu(tcon->fsUnixInfo.Capability)))
233 rc = CIFSSMBQFSPosixInfo(xid, tcon, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234
Steve French39da9842008-04-28 04:04:34 +0000235 /*
236 * Only need to call the old QFSInfo if failed on newer one,
237 * e.g. by OS/2.
238 **/
239 if (rc && (tcon->ses->capabilities & CAP_NT_SMBS))
240 rc = CIFSSMBQFSInfo(xid, tcon, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241
Steve French39da9842008-04-28 04:04:34 +0000242 /*
243 * Some old Windows servers also do not support level 103, retry with
244 * older level one if old server failed the previous call or we
245 * bypassed it because we detected that this was an older LANMAN sess
246 */
Steve French4523cc32007-04-30 20:13:06 +0000247 if (rc)
Steve French39da9842008-04-28 04:04:34 +0000248 rc = SMBOldQFSInfo(xid, tcon, buf);
249
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 FreeXid(xid);
Steve French39da9842008-04-28 04:04:34 +0000251 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252}
253
Nick Pigginb74c79e2011-01-07 17:49:58 +1100254static int cifs_permission(struct inode *inode, int mask, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255{
256 struct cifs_sb_info *cifs_sb;
257
258 cifs_sb = CIFS_SB(inode->i_sb);
259
Miklos Szeredif696a362008-07-31 13:41:58 +0200260 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
261 if ((mask & MAY_EXEC) && !execute_ok(inode))
262 return -EACCES;
263 else
264 return 0;
265 } else /* file mode might have been restricted at mount time
Steve French50c2f752007-07-13 00:33:32 +0000266 on the client (above and beyond ACL on servers) for
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 servers which do not support setting and viewing mode bits,
Steve French50c2f752007-07-13 00:33:32 +0000268 so allowing client to check permissions is useful */
Nick Pigginb74c79e2011-01-07 17:49:58 +1100269 return generic_permission(inode, mask, flags, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270}
271
Christoph Lametere18b8902006-12-06 20:33:20 -0800272static struct kmem_cache *cifs_inode_cachep;
273static struct kmem_cache *cifs_req_cachep;
274static struct kmem_cache *cifs_mid_cachep;
Christoph Lametere18b8902006-12-06 20:33:20 -0800275static struct kmem_cache *cifs_sm_req_cachep;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276mempool_t *cifs_sm_req_poolp;
277mempool_t *cifs_req_poolp;
278mempool_t *cifs_mid_poolp;
279
280static struct inode *
281cifs_alloc_inode(struct super_block *sb)
282{
283 struct cifsInodeInfo *cifs_inode;
Christoph Lametere94b1762006-12-06 20:33:17 -0800284 cifs_inode = kmem_cache_alloc(cifs_inode_cachep, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 if (!cifs_inode)
286 return NULL;
287 cifs_inode->cifsAttrs = 0x20; /* default */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 cifs_inode->time = 0;
289 /* Until the file is open and we have gotten oplock
290 info back from the server, can not assume caching of
291 file data or metadata */
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300292 cifs_set_oplock_level(cifs_inode, 0);
Jeff Layton9a8165f2008-10-17 21:03:20 -0400293 cifs_inode->delete_pending = false;
Jeff Laytondf2cf172010-02-12 07:44:16 -0500294 cifs_inode->invalid_mapping = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400296 cifs_inode->server_eof = 0;
Jeff Layton20054bd2011-01-07 11:30:27 -0500297 cifs_inode->uniqueid = 0;
298 cifs_inode->createtime = 0;
Steve French50c2f752007-07-13 00:33:32 +0000299
Steve French1b2b2122007-02-17 04:30:54 +0000300 /* Can not set i_flags here - they get immediately overwritten
301 to zero by the VFS */
302/* cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 INIT_LIST_HEAD(&cifs_inode->openFileList);
304 return &cifs_inode->vfs_inode;
305}
306
Nick Pigginfa0d7e3d2011-01-07 17:49:49 +1100307static void cifs_i_callback(struct rcu_head *head)
308{
309 struct inode *inode = container_of(head, struct inode, i_rcu);
310 INIT_LIST_HEAD(&inode->i_dentry);
311 kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
312}
313
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314static void
315cifs_destroy_inode(struct inode *inode)
316{
Nick Pigginfa0d7e3d2011-01-07 17:49:49 +1100317 call_rcu(&inode->i_rcu, cifs_i_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318}
319
Jeff Layton61f98ff2009-06-11 10:27:32 -0400320static void
Al Virob57922d2010-06-07 14:34:48 -0400321cifs_evict_inode(struct inode *inode)
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530322{
Al Virob57922d2010-06-07 14:34:48 -0400323 truncate_inode_pages(&inode->i_data, 0);
324 end_writeback(inode);
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530325 cifs_fscache_release_inode_cookie(inode);
326}
327
328static void
Jeff Layton61f98ff2009-06-11 10:27:32 -0400329cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
330{
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300331 struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr;
332 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr;
333
Jeff Layton61f98ff2009-06-11 10:27:32 -0400334 seq_printf(s, ",addr=");
335
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300336 switch (server->dstaddr.ss_family) {
Jeff Layton61f98ff2009-06-11 10:27:32 -0400337 case AF_INET:
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300338 seq_printf(s, "%pI4", &sa->sin_addr.s_addr);
Jeff Layton61f98ff2009-06-11 10:27:32 -0400339 break;
340 case AF_INET6:
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300341 seq_printf(s, "%pI6", &sa6->sin6_addr.s6_addr);
342 if (sa6->sin6_scope_id)
343 seq_printf(s, "%%%u", sa6->sin6_scope_id);
Jeff Layton61f98ff2009-06-11 10:27:32 -0400344 break;
345 default:
346 seq_printf(s, "(unknown)");
347 }
348}
349
Jeff Layton3e715512011-06-13 11:50:41 -0400350static void
351cifs_show_security(struct seq_file *s, struct TCP_Server_Info *server)
352{
353 seq_printf(s, ",sec=");
354
355 switch (server->secType) {
356 case LANMAN:
357 seq_printf(s, "lanman");
358 break;
359 case NTLMv2:
360 seq_printf(s, "ntlmv2");
361 break;
362 case NTLM:
363 seq_printf(s, "ntlm");
364 break;
365 case Kerberos:
366 seq_printf(s, "krb5");
367 break;
368 case RawNTLMSSP:
369 seq_printf(s, "ntlmssp");
370 break;
371 default:
372 /* shouldn't ever happen */
373 seq_printf(s, "unknown");
374 break;
375 }
376
377 if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
378 seq_printf(s, "i");
379}
380
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381/*
382 * cifs_show_options() is for displaying mount options in /proc/mounts.
383 * Not all settable options are displayed but most of the important
384 * ones are.
385 */
386static int
387cifs_show_options(struct seq_file *s, struct vfsmount *m)
388{
Jeff Layton8e047d02009-08-28 10:11:10 -0400389 struct cifs_sb_info *cifs_sb = CIFS_SB(m->mnt_sb);
Steve French96daf2b2011-05-27 04:34:02 +0000390 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
Ben Greear3eb9a882010-09-01 17:06:02 -0700391 struct sockaddr *srcaddr;
392 srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393
Jeff Layton3e715512011-06-13 11:50:41 -0400394 cifs_show_security(s, tcon->ses->server);
395
Jeff Layton8e047d02009-08-28 10:11:10 -0400396 seq_printf(s, ",unc=%s", tcon->treeName);
Jeff Layton29e07c82010-09-29 19:51:12 -0400397
398 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)
399 seq_printf(s, ",multiuser");
Steve French8727c8a2011-02-25 01:11:56 -0600400 else if (tcon->ses->user_name)
401 seq_printf(s, ",username=%s", tcon->ses->user_name);
Jeff Layton29e07c82010-09-29 19:51:12 -0400402
Jeff Layton8616e0f2009-06-11 10:27:28 -0400403 if (tcon->ses->domainName)
404 seq_printf(s, ",domain=%s", tcon->ses->domainName);
405
Ben Greear3eb9a882010-09-01 17:06:02 -0700406 if (srcaddr->sa_family != AF_UNSPEC) {
407 struct sockaddr_in *saddr4;
408 struct sockaddr_in6 *saddr6;
409 saddr4 = (struct sockaddr_in *)srcaddr;
410 saddr6 = (struct sockaddr_in6 *)srcaddr;
411 if (srcaddr->sa_family == AF_INET6)
412 seq_printf(s, ",srcaddr=%pI6c",
413 &saddr6->sin6_addr);
414 else if (srcaddr->sa_family == AF_INET)
415 seq_printf(s, ",srcaddr=%pI4",
416 &saddr4->sin_addr.s_addr);
417 else
418 seq_printf(s, ",srcaddr=BAD-AF:%i",
419 (int)(srcaddr->sa_family));
420 }
421
Jeff Layton8616e0f2009-06-11 10:27:28 -0400422 seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
Jeff Layton340481a32009-06-11 10:27:29 -0400423 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
424 seq_printf(s, ",forceuid");
Jeff Layton4486d6e2009-08-03 12:45:10 -0400425 else
426 seq_printf(s, ",noforceuid");
Jeff Layton340481a32009-06-11 10:27:29 -0400427
Jeff Layton8616e0f2009-06-11 10:27:28 -0400428 seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
Jeff Layton340481a32009-06-11 10:27:29 -0400429 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
430 seq_printf(s, ",forcegid");
Jeff Layton4486d6e2009-08-03 12:45:10 -0400431 else
432 seq_printf(s, ",noforcegid");
Jeff Layton8616e0f2009-06-11 10:27:28 -0400433
Jeff Layton61f98ff2009-06-11 10:27:32 -0400434 cifs_show_address(s, tcon->ses->server);
Jeff Layton8616e0f2009-06-11 10:27:28 -0400435
436 if (!tcon->unix_ext)
437 seq_printf(s, ",file_mode=0%o,dir_mode=0%o",
Steve French2b280fa2008-05-17 03:12:45 +0000438 cifs_sb->mnt_file_mode,
439 cifs_sb->mnt_dir_mode);
Jeff Layton8616e0f2009-06-11 10:27:28 -0400440 if (tcon->seal)
441 seq_printf(s, ",seal");
442 if (tcon->nocase)
443 seq_printf(s, ",nocase");
444 if (tcon->retry)
445 seq_printf(s, ",hard");
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000446 if (tcon->unix_ext)
447 seq_printf(s, ",unix");
448 else
449 seq_printf(s, ",nounix");
Jeff Layton8616e0f2009-06-11 10:27:28 -0400450 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
451 seq_printf(s, ",posixpaths");
452 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
453 seq_printf(s, ",setuids");
454 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
455 seq_printf(s, ",serverino");
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +0000456 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
457 seq_printf(s, ",rwpidforward");
458 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL)
459 seq_printf(s, ",forcemand");
Jeff Layton8616e0f2009-06-11 10:27:28 -0400460 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
461 seq_printf(s, ",directio");
462 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
463 seq_printf(s, ",nouser_xattr");
464 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
465 seq_printf(s, ",mapchars");
466 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
467 seq_printf(s, ",sfu");
468 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
469 seq_printf(s, ",nobrl");
470 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
471 seq_printf(s, ",cifsacl");
472 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
473 seq_printf(s, ",dynperm");
474 if (m->mnt_sb->s_flags & MS_POSIXACL)
475 seq_printf(s, ",acl");
Stefan Metzmacher736a3322010-07-30 14:56:00 +0200476 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
477 seq_printf(s, ",mfsymlinks");
Suresh Jayaraman476428f2010-11-24 17:49:07 +0530478 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE)
479 seq_printf(s, ",fsc");
Steve French2b280fa2008-05-17 03:12:45 +0000480
Jeff Layton8616e0f2009-06-11 10:27:28 -0400481 seq_printf(s, ",rsize=%d", cifs_sb->rsize);
482 seq_printf(s, ",wsize=%d", cifs_sb->wsize);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +0530483 /* convert actimeo and display it in seconds */
484 seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);
Jeff Layton8616e0f2009-06-11 10:27:28 -0400485
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 return 0;
487}
488
Al Viro42faad92008-04-24 07:21:56 -0400489static void cifs_umount_begin(struct super_block *sb)
Steve French68058e72005-10-10 10:34:22 -0700490{
Al Viro42faad92008-04-24 07:21:56 -0400491 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French96daf2b2011-05-27 04:34:02 +0000492 struct cifs_tcon *tcon;
Steve French68058e72005-10-10 10:34:22 -0700493
Steve French4523cc32007-04-30 20:13:06 +0000494 if (cifs_sb == NULL)
Steve French9e2e85f2005-10-10 14:28:38 -0700495 return;
496
Jeff Layton0d424ad2010-09-20 16:01:35 -0700497 tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500498
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530499 spin_lock(&cifs_tcp_ses_lock);
Steve Frenchad8034f2009-06-26 03:25:49 +0000500 if ((tcon->tc_count > 1) || (tcon->tidStatus == CifsExiting)) {
501 /* we have other mounts to same share or we have
502 already tried to force umount this and woken up
503 all waiting network requests, nothing to do */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530504 spin_unlock(&cifs_tcp_ses_lock);
Steve Frenchad8034f2009-06-26 03:25:49 +0000505 return;
506 } else if (tcon->tc_count == 1)
Steve French5e1253b2005-10-10 14:06:37 -0700507 tcon->tidStatus = CifsExiting;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530508 spin_unlock(&cifs_tcp_ses_lock);
Steve French5e1253b2005-10-10 14:06:37 -0700509
Steve French3a5ff612006-07-14 22:37:11 +0000510 /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
Steve French7b7abfe2005-11-09 15:21:09 -0800511 /* cancel_notify_requests(tcon); */
Steve French50c2f752007-07-13 00:33:32 +0000512 if (tcon->ses && tcon->ses->server) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000513 cFYI(1, "wake up tasks now - umount begin not complete");
Steve French9e2e85f2005-10-10 14:28:38 -0700514 wake_up_all(&tcon->ses->server->request_q);
Steve French6ab16d22005-11-29 20:55:11 -0800515 wake_up_all(&tcon->ses->server->response_q);
516 msleep(1); /* yield */
517 /* we have to kick the requests once more */
518 wake_up_all(&tcon->ses->server->response_q);
519 msleep(1);
Steve French5e1253b2005-10-10 14:06:37 -0700520 }
Steve French68058e72005-10-10 10:34:22 -0700521
522 return;
523}
Steve French68058e72005-10-10 10:34:22 -0700524
Steve Frenchbf97d282006-09-28 21:34:06 +0000525#ifdef CONFIG_CIFS_STATS2
526static int cifs_show_stats(struct seq_file *s, struct vfsmount *mnt)
527{
528 /* BB FIXME */
529 return 0;
530}
531#endif
532
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533static int cifs_remount(struct super_block *sb, int *flags, char *data)
534{
535 *flags |= MS_NODIRATIME;
536 return 0;
537}
538
Al Viro45321ac2010-06-07 13:43:19 -0400539static int cifs_drop_inode(struct inode *inode)
Jeff Layton12420ac2010-06-01 14:47:40 -0400540{
541 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
542
Al Viro45321ac2010-06-07 13:43:19 -0400543 /* no serverino => unconditional eviction */
544 return !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) ||
545 generic_drop_inode(inode);
Jeff Layton12420ac2010-06-01 14:47:40 -0400546}
547
Josef 'Jeff' Sipekee9b6d62007-02-12 00:55:41 -0800548static const struct super_operations cifs_super_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 .put_super = cifs_put_super,
550 .statfs = cifs_statfs,
551 .alloc_inode = cifs_alloc_inode,
552 .destroy_inode = cifs_destroy_inode,
Jeff Layton12420ac2010-06-01 14:47:40 -0400553 .drop_inode = cifs_drop_inode,
Al Virob57922d2010-06-07 14:34:48 -0400554 .evict_inode = cifs_evict_inode,
Jeff Layton12420ac2010-06-01 14:47:40 -0400555/* .delete_inode = cifs_delete_inode, */ /* Do not need above
556 function unless later we add lazy close of inodes or unless the
Steve French50c2f752007-07-13 00:33:32 +0000557 kernel forgets to call us with the same number of releases (closes)
558 as opens */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 .show_options = cifs_show_options,
Steve French7b7abfe2005-11-09 15:21:09 -0800560 .umount_begin = cifs_umount_begin,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 .remount_fs = cifs_remount,
Steve Frenchbf97d282006-09-28 21:34:06 +0000562#ifdef CONFIG_CIFS_STATS2
Steve Frenchf46d3e12006-09-30 01:08:55 +0000563 .show_stats = cifs_show_stats,
Steve Frenchbf97d282006-09-28 21:34:06 +0000564#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565};
566
Steve Frenchf87d39d2011-05-27 03:50:55 +0000567/*
568 * Get root dentry from superblock according to prefix path mount option.
569 * Return dentry with refcount + 1 on success and NULL otherwise.
570 */
571static struct dentry *
572cifs_get_root(struct smb_vol *vol, struct super_block *sb)
573{
574 int xid, rc;
575 struct inode *inode;
576 struct qstr name;
577 struct dentry *dparent = NULL, *dchild = NULL, *alias;
578 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
579 unsigned int i, full_len, len;
580 char *full_path = NULL, *pstart;
581 char sep;
582
583 full_path = cifs_build_path_to_root(vol, cifs_sb,
584 cifs_sb_master_tcon(cifs_sb));
585 if (full_path == NULL)
586 return NULL;
587
588 cFYI(1, "Get root dentry for %s", full_path);
589
590 xid = GetXid();
591 sep = CIFS_DIR_SEP(cifs_sb);
592 dparent = dget(sb->s_root);
593 full_len = strlen(full_path);
594 full_path[full_len] = sep;
595 pstart = full_path + 1;
596
597 for (i = 1, len = 0; i <= full_len; i++) {
598 if (full_path[i] != sep || !len) {
599 len++;
600 continue;
601 }
602
603 full_path[i] = 0;
604 cFYI(1, "get dentry for %s", pstart);
605
606 name.name = pstart;
607 name.len = len;
608 name.hash = full_name_hash(pstart, len);
609 dchild = d_lookup(dparent, &name);
610 if (dchild == NULL) {
611 cFYI(1, "not exists");
612 dchild = d_alloc(dparent, &name);
613 if (dchild == NULL) {
614 dput(dparent);
615 dparent = NULL;
616 goto out;
617 }
618 }
619
620 cFYI(1, "get inode");
621 if (dchild->d_inode == NULL) {
622 cFYI(1, "not exists");
623 inode = NULL;
624 if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
625 rc = cifs_get_inode_info_unix(&inode, full_path,
626 sb, xid);
627 else
628 rc = cifs_get_inode_info(&inode, full_path,
629 NULL, sb, xid, NULL);
630 if (rc) {
631 dput(dchild);
632 dput(dparent);
633 dparent = NULL;
634 goto out;
635 }
636 alias = d_materialise_unique(dchild, inode);
637 if (alias != NULL) {
638 dput(dchild);
639 if (IS_ERR(alias)) {
640 dput(dparent);
641 dparent = NULL;
642 goto out;
643 }
644 dchild = alias;
645 }
646 }
647 cFYI(1, "parent %p, child %p", dparent, dchild);
648
649 dput(dparent);
650 dparent = dchild;
651 len = 0;
652 pstart = full_path + i + 1;
653 full_path[i] = sep;
654 }
655out:
656 _FreeXid(xid);
657 kfree(full_path);
658 return dparent;
659}
660
Al Virod753ed92010-07-26 12:52:33 +0400661static struct dentry *
662cifs_do_mount(struct file_system_type *fs_type,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +0000663 int flags, const char *dev_name, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664{
665 int rc;
Jan Blunckdb719222010-08-15 22:51:10 +0200666 struct super_block *sb;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +0000667 struct cifs_sb_info *cifs_sb;
668 struct smb_vol *volume_info;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +0400669 struct cifs_mnt_data mnt_data;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +0000670 struct dentry *root;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671
Joe Perchesb6b38f72010-04-21 03:50:45 +0000672 cFYI(1, "Devname: %s flags: %d ", dev_name, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673
Pavel Shilovsky724d9f12011-05-05 09:55:12 +0000674 rc = cifs_setup_volume_info(&volume_info, (char *)data, dev_name);
675 if (rc)
676 return ERR_PTR(rc);
677
678 cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL);
679 if (cifs_sb == NULL) {
680 root = ERR_PTR(-ENOMEM);
Al Viroca171ba2011-06-17 08:49:12 -0400681 unload_nls(volume_info->local_nls);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +0000682 goto out;
683 }
684
Al Viro5d3bc602011-06-17 09:17:28 -0400685 cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL);
686 if (cifs_sb->mountdata == NULL) {
687 root = ERR_PTR(-ENOMEM);
688 unload_nls(volume_info->local_nls);
689 kfree(cifs_sb);
690 goto out;
691 }
692
Pavel Shilovsky724d9f12011-05-05 09:55:12 +0000693 cifs_setup_cifs_sb(volume_info, cifs_sb);
694
Pavel Shilovsky25c7f412011-05-26 23:35:47 +0400695 mnt_data.vol = volume_info;
696 mnt_data.cifs_sb = cifs_sb;
697 mnt_data.flags = flags;
698
699 sb = sget(fs_type, cifs_match_super, set_anon_super, &mnt_data);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +0000700 if (IS_ERR(sb)) {
Pavel Shilovsky724d9f12011-05-05 09:55:12 +0000701 root = ERR_CAST(sb);
Pavel Shilovsky641a58d2011-05-26 00:02:16 +0400702 goto out_cifs_sb;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +0000703 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704
Pavel Shilovsky25c7f412011-05-26 23:35:47 +0400705 if (sb->s_fs_info) {
706 cFYI(1, "Use existing superblock");
Al Viro5d3bc602011-06-17 09:17:28 -0400707 kfree(cifs_sb->mountdata);
Al Virod687ca382011-06-17 09:14:27 -0400708 unload_nls(cifs_sb->local_nls);
709 kfree(cifs_sb);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +0400710 goto out_shared;
711 }
712
Pavel Shilovskyb2e5cd32011-05-25 13:35:34 +0400713 sb->s_flags = flags;
714 /* BB should we make this contingent on mount parm? */
715 sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
716 sb->s_fs_info = cifs_sb;
717
718 rc = cifs_read_super(sb, volume_info, dev_name,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +0000719 flags & MS_SILENT ? 1 : 0);
720 if (rc) {
721 root = ERR_PTR(rc);
Pavel Shilovsky641a58d2011-05-26 00:02:16 +0400722 goto out_super;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +0000723 }
724
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 sb->s_flags |= MS_ACTIVE;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +0000726
Steve Frenchf87d39d2011-05-27 03:50:55 +0000727 root = cifs_get_root(volume_info, sb);
728 if (root == NULL)
729 goto out_super;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +0400730
Steve Frenchf87d39d2011-05-27 03:50:55 +0000731 cFYI(1, "dentry root is: %p", root);
Pavel Shilovsky641a58d2011-05-26 00:02:16 +0400732 goto out;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +0000733
Pavel Shilovsky25c7f412011-05-26 23:35:47 +0400734out_shared:
735 root = cifs_get_root(volume_info, sb);
736 if (root)
737 cFYI(1, "dentry root is: %p", root);
738 goto out;
739
Pavel Shilovsky641a58d2011-05-26 00:02:16 +0400740out_super:
Pavel Shilovsky641a58d2011-05-26 00:02:16 +0400741 deactivate_locked_super(sb);
Al Viro6d686172011-06-17 08:34:57 -0400742 goto out;
Pavel Shilovsky641a58d2011-05-26 00:02:16 +0400743
744out_cifs_sb:
Al Viro5d3bc602011-06-17 09:17:28 -0400745 kfree(cifs_sb->mountdata);
Pavel Shilovskyb2e5cd32011-05-25 13:35:34 +0400746 unload_nls(cifs_sb->local_nls);
Pavel Shilovsky724d9f12011-05-05 09:55:12 +0000747 kfree(cifs_sb);
Pavel Shilovsky641a58d2011-05-26 00:02:16 +0400748
749out:
Pavel Shilovsky724d9f12011-05-05 09:55:12 +0000750 cifs_cleanup_volume_info(&volume_info);
751 return root;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752}
753
Badari Pulavarty027445c2006-09-30 23:28:46 -0700754static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
755 unsigned long nr_segs, loff_t pos)
Steve French87c89dd2005-11-17 17:03:00 -0800756{
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -0800757 struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
Steve French87c89dd2005-11-17 17:03:00 -0800758 ssize_t written;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -0500759 int rc;
Steve French87c89dd2005-11-17 17:03:00 -0800760
Badari Pulavarty027445c2006-09-30 23:28:46 -0700761 written = generic_file_aio_write(iocb, iov, nr_segs, pos);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -0500762
763 if (CIFS_I(inode)->clientCanCacheAll)
764 return written;
765
766 rc = filemap_fdatawrite(inode->i_mapping);
767 if (rc)
768 cFYI(1, "cifs_file_aio_write: %d rc on %p inode", rc, inode);
769
Steve French87c89dd2005-11-17 17:03:00 -0800770 return written;
771}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772
Steve Frenchc32a0b62006-01-12 14:41:28 -0800773static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
774{
775 /* origin == SEEK_END => we must revalidate the cached file length */
Steve French0889a942006-09-23 22:11:07 +0000776 if (origin == SEEK_END) {
Pavel Shilovsky6feb9892011-04-07 18:18:11 +0400777 int rc;
778 struct inode *inode = file->f_path.dentry->d_inode;
Steve French030e9d82007-02-01 04:27:59 +0000779
Pavel Shilovsky6feb9892011-04-07 18:18:11 +0400780 /*
781 * We need to be sure that all dirty pages are written and the
782 * server has the newest file length.
783 */
784 if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping &&
785 inode->i_mapping->nrpages != 0) {
786 rc = filemap_fdatawait(inode->i_mapping);
Steve French156ecb22011-05-20 17:00:01 +0000787 if (rc) {
788 mapping_set_error(inode->i_mapping, rc);
789 return rc;
790 }
Pavel Shilovsky6feb9892011-04-07 18:18:11 +0400791 }
792 /*
793 * Some applications poll for the file length in this strange
794 * way so we must seek to end on non-oplocked files by
795 * setting the revalidate time to zero.
796 */
797 CIFS_I(inode)->time = 0;
Steve French030e9d82007-02-01 04:27:59 +0000798
Pavel Shilovsky6feb9892011-04-07 18:18:11 +0400799 rc = cifs_revalidate_file_attr(file);
800 if (rc < 0)
801 return (loff_t)rc;
Steve Frenchc32a0b62006-01-12 14:41:28 -0800802 }
Andi Kleen9465efc2008-06-27 11:05:24 +0200803 return generic_file_llseek_unlocked(file, offset, origin);
Steve Frenchc32a0b62006-01-12 14:41:28 -0800804}
805
Steve French84210e92008-10-23 04:42:37 +0000806static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
807{
Arnd Bergmannb89f4322010-09-18 15:09:31 +0200808 /* note that this is called by vfs setlease with lock_flocks held
809 to protect *lease from going away */
Steve French84210e92008-10-23 04:42:37 +0000810 struct inode *inode = file->f_path.dentry->d_inode;
Jeff Laytonba00ba62010-09-20 16:01:31 -0700811 struct cifsFileInfo *cfile = file->private_data;
Steve French84210e92008-10-23 04:42:37 +0000812
813 if (!(S_ISREG(inode->i_mode)))
814 return -EINVAL;
815
816 /* check if file is oplocked */
817 if (((arg == F_RDLCK) &&
818 (CIFS_I(inode)->clientCanCacheRead)) ||
819 ((arg == F_WRLCK) &&
820 (CIFS_I(inode)->clientCanCacheAll)))
821 return generic_setlease(file, arg, lease);
Jeff Layton13cfb732010-09-29 19:51:11 -0400822 else if (tlink_tcon(cfile->tlink)->local_lease &&
823 !CIFS_I(inode)->clientCanCacheRead)
Steve French84210e92008-10-23 04:42:37 +0000824 /* If the server claims to support oplock on this
825 file, then we still need to check oplock even
826 if the local_lease mount option is set, but there
827 are servers which do not support oplock for which
828 this mount option may be useful if the user
829 knows that the file won't be changed on the server
830 by anyone else */
831 return generic_setlease(file, arg, lease);
Christoph Hellwig51ee4b82010-10-31 08:35:10 -0400832 else
Steve French84210e92008-10-23 04:42:37 +0000833 return -EAGAIN;
834}
Steve French84210e92008-10-23 04:42:37 +0000835
Igor Mammedove6ab1582008-01-11 01:49:48 +0000836struct file_system_type cifs_fs_type = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 .owner = THIS_MODULE,
838 .name = "cifs",
Al Virod753ed92010-07-26 12:52:33 +0400839 .mount = cifs_do_mount,
Al Viro6d686172011-06-17 08:34:57 -0400840 .kill_sb = cifs_kill_sb,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 /* .fs_flags */
842};
Arjan van de Ven754661f2007-02-12 00:55:38 -0800843const struct inode_operations cifs_dir_inode_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 .create = cifs_create,
845 .lookup = cifs_lookup,
846 .getattr = cifs_getattr,
847 .unlink = cifs_unlink,
848 .link = cifs_hardlink,
849 .mkdir = cifs_mkdir,
850 .rmdir = cifs_rmdir,
851 .rename = cifs_rename,
852 .permission = cifs_permission,
853/* revalidate:cifs_revalidate, */
854 .setattr = cifs_setattr,
855 .symlink = cifs_symlink,
856 .mknod = cifs_mknod,
857#ifdef CONFIG_CIFS_XATTR
858 .setxattr = cifs_setxattr,
859 .getxattr = cifs_getxattr,
860 .listxattr = cifs_listxattr,
861 .removexattr = cifs_removexattr,
862#endif
863};
864
Arjan van de Ven754661f2007-02-12 00:55:38 -0800865const struct inode_operations cifs_file_inode_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866/* revalidate:cifs_revalidate, */
867 .setattr = cifs_setattr,
868 .getattr = cifs_getattr, /* do we need this anymore? */
869 .rename = cifs_rename,
870 .permission = cifs_permission,
871#ifdef CONFIG_CIFS_XATTR
872 .setxattr = cifs_setxattr,
873 .getxattr = cifs_getxattr,
874 .listxattr = cifs_listxattr,
875 .removexattr = cifs_removexattr,
Steve French50c2f752007-07-13 00:33:32 +0000876#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877};
878
Arjan van de Ven754661f2007-02-12 00:55:38 -0800879const struct inode_operations cifs_symlink_inode_ops = {
Steve French50c2f752007-07-13 00:33:32 +0000880 .readlink = generic_readlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 .follow_link = cifs_follow_link,
882 .put_link = cifs_put_link,
883 .permission = cifs_permission,
884 /* BB add the following two eventually */
885 /* revalidate: cifs_revalidate,
886 setattr: cifs_notify_change, *//* BB do we need notify change */
887#ifdef CONFIG_CIFS_XATTR
888 .setxattr = cifs_setxattr,
889 .getxattr = cifs_getxattr,
890 .listxattr = cifs_listxattr,
891 .removexattr = cifs_removexattr,
Steve French50c2f752007-07-13 00:33:32 +0000892#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893};
894
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800895const struct file_operations cifs_file_ops = {
Steve French87c89dd2005-11-17 17:03:00 -0800896 .read = do_sync_read,
897 .write = do_sync_write,
Steve French87c89dd2005-11-17 17:03:00 -0800898 .aio_read = generic_file_aio_read,
899 .aio_write = cifs_file_aio_write,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 .open = cifs_open,
901 .release = cifs_close,
902 .lock = cifs_lock,
903 .fsync = cifs_fsync,
904 .flush = cifs_flush,
905 .mmap = cifs_file_mmap,
Jens Axboe5ffc4ef2007-06-01 11:49:19 +0200906 .splice_read = generic_file_splice_read,
Steve Frenchc32a0b62006-01-12 14:41:28 -0800907 .llseek = cifs_llseek,
Steve Frenchc67593a2005-04-28 22:41:04 -0700908#ifdef CONFIG_CIFS_POSIX
Steve Frenchf9ddcca2008-05-15 05:51:55 +0000909 .unlocked_ioctl = cifs_ioctl,
Steve Frenchc67593a2005-04-28 22:41:04 -0700910#endif /* CONFIG_CIFS_POSIX */
Steve French84210e92008-10-23 04:42:37 +0000911 .setlease = cifs_setlease,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912};
913
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +0300914const struct file_operations cifs_file_strict_ops = {
915 .read = do_sync_read,
916 .write = do_sync_write,
Pavel Shilovskya70307e2010-12-14 11:50:41 +0300917 .aio_read = cifs_strict_readv,
Pavel Shilovsky72432ff2011-01-24 14:16:35 -0500918 .aio_write = cifs_strict_writev,
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +0300919 .open = cifs_open,
920 .release = cifs_close,
921 .lock = cifs_lock,
922 .fsync = cifs_strict_fsync,
923 .flush = cifs_flush,
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +0300924 .mmap = cifs_file_strict_mmap,
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +0300925 .splice_read = generic_file_splice_read,
926 .llseek = cifs_llseek,
927#ifdef CONFIG_CIFS_POSIX
928 .unlocked_ioctl = cifs_ioctl,
929#endif /* CONFIG_CIFS_POSIX */
930 .setlease = cifs_setlease,
931};
932
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800933const struct file_operations cifs_file_direct_ops = {
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +0300934 /* BB reevaluate whether they can be done with directio, no cache */
935 .read = do_sync_read,
936 .write = do_sync_write,
937 .aio_read = cifs_user_readv,
938 .aio_write = cifs_user_writev,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 .open = cifs_open,
940 .release = cifs_close,
941 .lock = cifs_lock,
942 .fsync = cifs_fsync,
943 .flush = cifs_flush,
Steve Frencha994b8f2009-12-07 05:44:46 +0000944 .mmap = cifs_file_mmap,
Jens Axboe5ffc4ef2007-06-01 11:49:19 +0200945 .splice_read = generic_file_splice_read,
Steve Frenchc67593a2005-04-28 22:41:04 -0700946#ifdef CONFIG_CIFS_POSIX
Steve Frenchf9ddcca2008-05-15 05:51:55 +0000947 .unlocked_ioctl = cifs_ioctl,
Steve Frenchc67593a2005-04-28 22:41:04 -0700948#endif /* CONFIG_CIFS_POSIX */
Steve Frenchc32a0b62006-01-12 14:41:28 -0800949 .llseek = cifs_llseek,
Steve French84210e92008-10-23 04:42:37 +0000950 .setlease = cifs_setlease,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951};
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +0300952
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800953const struct file_operations cifs_file_nobrl_ops = {
Steve French87c89dd2005-11-17 17:03:00 -0800954 .read = do_sync_read,
955 .write = do_sync_write,
Steve French87c89dd2005-11-17 17:03:00 -0800956 .aio_read = generic_file_aio_read,
957 .aio_write = cifs_file_aio_write,
958 .open = cifs_open,
959 .release = cifs_close,
960 .fsync = cifs_fsync,
961 .flush = cifs_flush,
962 .mmap = cifs_file_mmap,
Jens Axboe5ffc4ef2007-06-01 11:49:19 +0200963 .splice_read = generic_file_splice_read,
Steve Frenchc32a0b62006-01-12 14:41:28 -0800964 .llseek = cifs_llseek,
Steve French8b94bcb2005-11-11 11:41:00 -0800965#ifdef CONFIG_CIFS_POSIX
Steve Frenchf9ddcca2008-05-15 05:51:55 +0000966 .unlocked_ioctl = cifs_ioctl,
Steve French8b94bcb2005-11-11 11:41:00 -0800967#endif /* CONFIG_CIFS_POSIX */
Steve French84210e92008-10-23 04:42:37 +0000968 .setlease = cifs_setlease,
Steve French8b94bcb2005-11-11 11:41:00 -0800969};
970
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +0300971const struct file_operations cifs_file_strict_nobrl_ops = {
972 .read = do_sync_read,
973 .write = do_sync_write,
Pavel Shilovskya70307e2010-12-14 11:50:41 +0300974 .aio_read = cifs_strict_readv,
Pavel Shilovsky72432ff2011-01-24 14:16:35 -0500975 .aio_write = cifs_strict_writev,
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +0300976 .open = cifs_open,
977 .release = cifs_close,
978 .fsync = cifs_strict_fsync,
979 .flush = cifs_flush,
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +0300980 .mmap = cifs_file_strict_mmap,
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +0300981 .splice_read = generic_file_splice_read,
982 .llseek = cifs_llseek,
983#ifdef CONFIG_CIFS_POSIX
984 .unlocked_ioctl = cifs_ioctl,
985#endif /* CONFIG_CIFS_POSIX */
986 .setlease = cifs_setlease,
987};
988
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800989const struct file_operations cifs_file_direct_nobrl_ops = {
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +0300990 /* BB reevaluate whether they can be done with directio, no cache */
991 .read = do_sync_read,
992 .write = do_sync_write,
993 .aio_read = cifs_user_readv,
994 .aio_write = cifs_user_writev,
Steve French87c89dd2005-11-17 17:03:00 -0800995 .open = cifs_open,
996 .release = cifs_close,
997 .fsync = cifs_fsync,
998 .flush = cifs_flush,
Pavel Shilovsky810627a02010-03-27 02:00:49 +0000999 .mmap = cifs_file_mmap,
Jens Axboe5ffc4ef2007-06-01 11:49:19 +02001000 .splice_read = generic_file_splice_read,
Steve French8b94bcb2005-11-11 11:41:00 -08001001#ifdef CONFIG_CIFS_POSIX
Steve Frenchf9ddcca2008-05-15 05:51:55 +00001002 .unlocked_ioctl = cifs_ioctl,
Steve French8b94bcb2005-11-11 11:41:00 -08001003#endif /* CONFIG_CIFS_POSIX */
Steve Frenchc32a0b62006-01-12 14:41:28 -08001004 .llseek = cifs_llseek,
Steve French84210e92008-10-23 04:42:37 +00001005 .setlease = cifs_setlease,
Steve French8b94bcb2005-11-11 11:41:00 -08001006};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001008const struct file_operations cifs_dir_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 .readdir = cifs_readdir,
1010 .release = cifs_closedir,
1011 .read = generic_read_dir,
Steve Frenchf9ddcca2008-05-15 05:51:55 +00001012 .unlocked_ioctl = cifs_ioctl,
Christoph Hellwig3222a3e2008-09-03 21:53:01 +02001013 .llseek = generic_file_llseek,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014};
1015
1016static void
Alexey Dobriyan51cc5062008-07-25 19:45:34 -07001017cifs_init_once(void *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018{
1019 struct cifsInodeInfo *cifsi = inode;
1020
Christoph Lametera35afb82007-05-16 22:10:57 -07001021 inode_init_once(&cifsi->vfs_inode);
1022 INIT_LIST_HEAD(&cifsi->lockList);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023}
1024
1025static int
1026cifs_init_inodecache(void)
1027{
1028 cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
Steve French26f57362007-08-30 22:09:15 +00001029 sizeof(struct cifsInodeInfo),
Paul Jacksonfffb60f2006-03-24 03:16:06 -08001030 0, (SLAB_RECLAIM_ACCOUNT|
1031 SLAB_MEM_SPREAD),
Paul Mundt20c2df82007-07-20 10:11:58 +09001032 cifs_init_once);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 if (cifs_inode_cachep == NULL)
1034 return -ENOMEM;
1035
1036 return 0;
1037}
1038
1039static void
1040cifs_destroy_inodecache(void)
1041{
Alexey Dobriyan1a1d92c2006-09-27 01:49:40 -07001042 kmem_cache_destroy(cifs_inode_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043}
1044
1045static int
1046cifs_init_request_bufs(void)
1047{
Steve French4523cc32007-04-30 20:13:06 +00001048 if (CIFSMaxBufSize < 8192) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 /* Buffer size can not be smaller than 2 * PATH_MAX since maximum
1050 Unicode path name has to fit in any SMB/CIFS path based frames */
1051 CIFSMaxBufSize = 8192;
1052 } else if (CIFSMaxBufSize > 1024*127) {
1053 CIFSMaxBufSize = 1024 * 127;
1054 } else {
1055 CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/
1056 }
Joe Perchesb6b38f72010-04-21 03:50:45 +00001057/* cERROR(1, "CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 cifs_req_cachep = kmem_cache_create("cifs_request",
1059 CIFSMaxBufSize +
1060 MAX_CIFS_HDR_SIZE, 0,
Paul Mundt20c2df82007-07-20 10:11:58 +09001061 SLAB_HWCACHE_ALIGN, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 if (cifs_req_cachep == NULL)
1063 return -ENOMEM;
1064
Steve French4523cc32007-04-30 20:13:06 +00001065 if (cifs_min_rcv < 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 cifs_min_rcv = 1;
1067 else if (cifs_min_rcv > 64) {
1068 cifs_min_rcv = 64;
Joe Perchesb6b38f72010-04-21 03:50:45 +00001069 cERROR(1, "cifs_min_rcv set to maximum (64)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 }
1071
Matthew Dobson93d23412006-03-26 01:37:50 -08001072 cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv,
1073 cifs_req_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074
Steve French4523cc32007-04-30 20:13:06 +00001075 if (cifs_req_poolp == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 kmem_cache_destroy(cifs_req_cachep);
1077 return -ENOMEM;
1078 }
Steve Frenchec637e32005-12-12 20:53:18 -08001079 /* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 almost all handle based requests (but not write response, nor is it
1081 sufficient for path based requests). A smaller size would have
Steve French50c2f752007-07-13 00:33:32 +00001082 been more efficient (compacting multiple slab items on one 4k page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 for the case in which debug was on, but this larger size allows
1084 more SMBs to use small buffer alloc and is still much more
Steve French6dc0f872007-07-06 23:13:06 +00001085 efficient to alloc 1 per page off the slab compared to 17K (5page)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 alloc of large cifs buffers even when page debugging is on */
1087 cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq",
Steve French6dc0f872007-07-06 23:13:06 +00001088 MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN,
Paul Mundt20c2df82007-07-20 10:11:58 +09001089 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 if (cifs_sm_req_cachep == NULL) {
1091 mempool_destroy(cifs_req_poolp);
1092 kmem_cache_destroy(cifs_req_cachep);
Steve French6dc0f872007-07-06 23:13:06 +00001093 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 }
1095
Steve French4523cc32007-04-30 20:13:06 +00001096 if (cifs_min_small < 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 cifs_min_small = 2;
1098 else if (cifs_min_small > 256) {
1099 cifs_min_small = 256;
Joe Perchesb6b38f72010-04-21 03:50:45 +00001100 cFYI(1, "cifs_min_small set to maximum (256)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 }
1102
Matthew Dobson93d23412006-03-26 01:37:50 -08001103 cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small,
1104 cifs_sm_req_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105
Steve French4523cc32007-04-30 20:13:06 +00001106 if (cifs_sm_req_poolp == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 mempool_destroy(cifs_req_poolp);
1108 kmem_cache_destroy(cifs_req_cachep);
1109 kmem_cache_destroy(cifs_sm_req_cachep);
1110 return -ENOMEM;
1111 }
1112
1113 return 0;
1114}
1115
1116static void
1117cifs_destroy_request_bufs(void)
1118{
1119 mempool_destroy(cifs_req_poolp);
Alexey Dobriyan1a1d92c2006-09-27 01:49:40 -07001120 kmem_cache_destroy(cifs_req_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 mempool_destroy(cifs_sm_req_poolp);
Alexey Dobriyan1a1d92c2006-09-27 01:49:40 -07001122 kmem_cache_destroy(cifs_sm_req_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123}
1124
1125static int
1126cifs_init_mids(void)
1127{
1128 cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
Steve French26f57362007-08-30 22:09:15 +00001129 sizeof(struct mid_q_entry), 0,
1130 SLAB_HWCACHE_ALIGN, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 if (cifs_mid_cachep == NULL)
1132 return -ENOMEM;
1133
Matthew Dobson93d23412006-03-26 01:37:50 -08001134 /* 3 is a reasonable minimum number of simultaneous operations */
1135 cifs_mid_poolp = mempool_create_slab_pool(3, cifs_mid_cachep);
Steve French4523cc32007-04-30 20:13:06 +00001136 if (cifs_mid_poolp == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 kmem_cache_destroy(cifs_mid_cachep);
1138 return -ENOMEM;
1139 }
1140
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 return 0;
1142}
1143
1144static void
1145cifs_destroy_mids(void)
1146{
1147 mempool_destroy(cifs_mid_poolp);
Alexey Dobriyan1a1d92c2006-09-27 01:49:40 -07001148 kmem_cache_destroy(cifs_mid_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149}
1150
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151static int __init
1152init_cifs(void)
1153{
1154 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 cifs_proc_init();
Jeff Laytone7ddee92008-11-14 13:44:38 -05001156 INIT_LIST_HEAD(&cifs_tcp_ses_list);
Steve French0eff0e22011-02-24 05:39:23 +00001157#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */
Steve French4ca9c192005-10-10 19:52:13 -07001158 INIT_LIST_HEAD(&GlobalDnotifyReqList);
1159 INIT_LIST_HEAD(&GlobalDnotifyRsp_Q);
Steve French0eff0e22011-02-24 05:39:23 +00001160#endif /* was needed for dnotify, and will be needed for inotify when VFS fix */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161/*
1162 * Initialize Global counters
1163 */
1164 atomic_set(&sesInfoAllocCount, 0);
1165 atomic_set(&tconInfoAllocCount, 0);
Steve French6dc0f872007-07-06 23:13:06 +00001166 atomic_set(&tcpSesAllocCount, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 atomic_set(&tcpSesReconnectCount, 0);
1168 atomic_set(&tconInfoReconnectCount, 0);
1169
1170 atomic_set(&bufAllocCount, 0);
Steve French4498eed52005-12-03 13:58:57 -08001171 atomic_set(&smBufAllocCount, 0);
1172#ifdef CONFIG_CIFS_STATS2
1173 atomic_set(&totBufAllocCount, 0);
1174 atomic_set(&totSmBufAllocCount, 0);
1175#endif /* CONFIG_CIFS_STATS2 */
1176
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 atomic_set(&midCount, 0);
1178 GlobalCurrentXid = 0;
1179 GlobalTotalActiveXid = 0;
1180 GlobalMaxActiveXid = 0;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05301181 spin_lock_init(&cifs_tcp_ses_lock);
Jeff Layton44772882010-10-15 15:34:03 -04001182 spin_lock_init(&cifs_file_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 spin_lock_init(&GlobalMid_Lock);
1184
Steve French4523cc32007-04-30 20:13:06 +00001185 if (cifs_max_pending < 2) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 cifs_max_pending = 2;
Joe Perchesb6b38f72010-04-21 03:50:45 +00001187 cFYI(1, "cifs_max_pending set to min of 2");
Steve French4523cc32007-04-30 20:13:06 +00001188 } else if (cifs_max_pending > 256) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 cifs_max_pending = 256;
Joe Perchesb6b38f72010-04-21 03:50:45 +00001190 cFYI(1, "cifs_max_pending set to max of 256");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 }
1192
Suresh Jayaramanf579cf32010-07-05 18:11:50 +05301193 rc = cifs_fscache_register();
1194 if (rc)
Steve Frenchd3bf5222010-09-22 19:15:36 +00001195 goto out_clean_proc;
Suresh Jayaramanf579cf32010-07-05 18:11:50 +05301196
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 rc = cifs_init_inodecache();
Steve French45af7a02006-04-21 22:52:25 +00001198 if (rc)
Steve Frenchd3bf5222010-09-22 19:15:36 +00001199 goto out_unreg_fscache;
Steve French45af7a02006-04-21 22:52:25 +00001200
1201 rc = cifs_init_mids();
1202 if (rc)
1203 goto out_destroy_inodecache;
1204
1205 rc = cifs_init_request_bufs();
1206 if (rc)
1207 goto out_destroy_mids;
1208
Jeff Layton84a15b92007-11-03 05:02:24 +00001209#ifdef CONFIG_CIFS_UPCALL
1210 rc = register_key_type(&cifs_spnego_key_type);
1211 if (rc)
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -05001212 goto out_destroy_request_bufs;
1213#endif /* CONFIG_CIFS_UPCALL */
1214
1215#ifdef CONFIG_CIFS_ACL
1216 rc = init_cifs_idmap();
1217 if (rc)
Shirish Pargaonkarc4aca0c2011-05-06 02:35:00 -05001218 goto out_register_key_type;
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -05001219#endif /* CONFIG_CIFS_ACL */
1220
1221 rc = register_filesystem(&cifs_fs_type);
1222 if (rc)
Shirish Pargaonkarc4aca0c2011-05-06 02:35:00 -05001223 goto out_init_cifs_idmap;
Steve French45af7a02006-04-21 22:52:25 +00001224
Steve French45af7a02006-04-21 22:52:25 +00001225 return 0;
1226
Shirish Pargaonkarc4aca0c2011-05-06 02:35:00 -05001227out_init_cifs_idmap:
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -05001228#ifdef CONFIG_CIFS_ACL
1229 exit_cifs_idmap();
Shirish Pargaonkarc4aca0c2011-05-06 02:35:00 -05001230out_register_key_type:
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -05001231#endif
1232#ifdef CONFIG_CIFS_UPCALL
1233 unregister_key_type(&cifs_spnego_key_type);
Shirish Pargaonkarc4aca0c2011-05-06 02:35:00 -05001234out_destroy_request_bufs:
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -05001235#endif
Steve French45af7a02006-04-21 22:52:25 +00001236 cifs_destroy_request_bufs();
Steve Frenchd3bf5222010-09-22 19:15:36 +00001237out_destroy_mids:
Steve French45af7a02006-04-21 22:52:25 +00001238 cifs_destroy_mids();
Steve Frenchd3bf5222010-09-22 19:15:36 +00001239out_destroy_inodecache:
Steve French45af7a02006-04-21 22:52:25 +00001240 cifs_destroy_inodecache();
Steve Frenchd3bf5222010-09-22 19:15:36 +00001241out_unreg_fscache:
Suresh Jayaramanf579cf32010-07-05 18:11:50 +05301242 cifs_fscache_unregister();
Steve Frenchd3bf5222010-09-22 19:15:36 +00001243out_clean_proc:
1244 cifs_proc_clean();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 return rc;
1246}
1247
1248static void __exit
1249exit_cifs(void)
1250{
Joe Perchesb6b38f72010-04-21 03:50:45 +00001251 cFYI(DBG2, "exit_cifs");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 cifs_proc_clean();
Suresh Jayaramanf579cf32010-07-05 18:11:50 +05301253 cifs_fscache_unregister();
Steve French61033352008-01-09 16:21:36 +00001254#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov78d31a32008-04-24 12:56:07 +04001255 cifs_dfs_release_automount_timer();
Steve French61033352008-01-09 16:21:36 +00001256#endif
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -05001257#ifdef CONFIG_CIFS_ACL
1258 cifs_destroy_idmaptrees();
1259 exit_cifs_idmap();
1260#endif
Jeff Layton84a15b92007-11-03 05:02:24 +00001261#ifdef CONFIG_CIFS_UPCALL
1262 unregister_key_type(&cifs_spnego_key_type);
1263#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 unregister_filesystem(&cifs_fs_type);
1265 cifs_destroy_inodecache();
1266 cifs_destroy_mids();
1267 cifs_destroy_request_bufs();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268}
1269
1270MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
Steve French6dc0f872007-07-06 23:13:06 +00001271MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272MODULE_DESCRIPTION
Steve French63135e02007-07-17 17:34:02 +00001273 ("VFS to access servers complying with the SNIA CIFS Specification "
1274 "e.g. Samba and Windows");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275MODULE_VERSION(CIFS_VERSION);
1276module_init(init_cifs)
1277module_exit(exit_cifs)