blob: bb39afcc6f3862e71bf1688822684ec40ea4e9ae [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
107cifs_read_super(struct super_block *sb, void *data,
108 const char *devname, int silent)
109{
110 struct inode *inode;
111 struct cifs_sb_info *cifs_sb;
112 int rc = 0;
Steve French50c2f752007-07-13 00:33:32 +0000113
Steve French1b2b2122007-02-17 04:30:54 +0000114 /* BB should we make this contingent on mount parm? */
115 sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
Steve French790fe572007-07-07 19:25:05 +0000116 sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 cifs_sb = CIFS_SB(sb);
Steve French4523cc32007-04-30 20:13:06 +0000118 if (cifs_sb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120
Jeff Layton0dd12c22010-10-08 12:20:12 -0400121 spin_lock_init(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -0400122 cifs_sb->tlink_tree = RB_ROOT;
Jeff Layton0dd12c22010-10-08 12:20:12 -0400123
Jens Axboe8044f7f2010-04-22 12:09:48 +0200124 rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
125 if (rc) {
126 kfree(cifs_sb);
127 return rc;
128 }
Jeff Layton2b6c26a2011-03-25 16:25:57 -0400129 cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages;
Jens Axboe8044f7f2010-04-22 12:09:48 +0200130
Igor Mammedove6ab1582008-01-11 01:49:48 +0000131#ifdef CONFIG_CIFS_DFS_UPCALL
Sean Finney5167f112011-04-11 13:19:34 +0000132 /*
133 * Copy mount params to sb for use in submounts. Better to do
134 * the copy here and deal with the error before cleanup gets
135 * complicated post-mount.
136 */
Steve French79ee9a82008-06-10 21:37:02 +0000137 if (data) {
Sean Finney5167f112011-04-11 13:19:34 +0000138 cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL);
Steve French79ee9a82008-06-10 21:37:02 +0000139 if (cifs_sb->mountdata == NULL) {
Jens Axboe8044f7f2010-04-22 12:09:48 +0200140 bdi_destroy(&cifs_sb->bdi);
Steve French79ee9a82008-06-10 21:37:02 +0000141 kfree(sb->s_fs_info);
142 sb->s_fs_info = NULL;
143 return -ENOMEM;
144 }
Igor Mammedove6ab1582008-01-11 01:49:48 +0000145 }
Igor Mammedove6ab1582008-01-11 01:49:48 +0000146#endif
147
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148 rc = cifs_mount(sb, cifs_sb, data, devname);
149
150 if (rc) {
151 if (!silent)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000152 cERROR(1, "cifs_mount failed w/return code = %d", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 goto out_mount_failed;
154 }
155
156 sb->s_magic = CIFS_MAGIC_NUMBER;
157 sb->s_op = &cifs_super_ops;
Jens Axboe8044f7f2010-04-22 12:09:48 +0200158 sb->s_bdi = &cifs_sb->bdi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 sb->s_blocksize = CIFS_MAX_MSGSIZE;
160 sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
Shirish Pargaonkar9b6763e2011-02-21 23:56:59 -0600161 inode = cifs_root_iget(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162
David Howellsce634ab2008-02-07 00:15:33 -0800163 if (IS_ERR(inode)) {
164 rc = PTR_ERR(inode);
165 inode = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 goto out_no_root;
167 }
168
169 sb->s_root = d_alloc_root(inode);
170
171 if (!sb->s_root) {
172 rc = -ENOMEM;
173 goto out_no_root;
174 }
Steve French50c2f752007-07-13 00:33:32 +0000175
Al Viro1c929cf2010-12-18 11:43:51 -0500176 /* do that *after* d_alloc_root() - we want NULL ->d_op for root here */
177 if (cifs_sb_master_tcon(cifs_sb)->nocase)
178 sb->s_d_op = &cifs_ci_dentry_ops;
179 else
180 sb->s_d_op = &cifs_dentry_ops;
181
Shirish Pargaonkar25720872011-02-25 10:48:55 -0600182#ifdef CIFS_NFSD_EXPORT
Steve French7521a3c2007-07-11 18:30:34 +0000183 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000184 cFYI(1, "export ops supported");
Steve French7521a3c2007-07-11 18:30:34 +0000185 sb->s_export_op = &cifs_export_ops;
186 }
Shirish Pargaonkar25720872011-02-25 10:48:55 -0600187#endif /* CIFS_NFSD_EXPORT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188
189 return 0;
190
191out_no_root:
Joe Perchesb6b38f72010-04-21 03:50:45 +0000192 cERROR(1, "cifs_read_super: get root inode failed");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 if (inode)
194 iput(inode);
Steve French54b46022008-08-11 22:31:40 +0000195
Steve French2c731af2008-08-11 22:28:53 +0000196 cifs_umount(sb, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197
198out_mount_failed:
Steve French4523cc32007-04-30 20:13:06 +0000199 if (cifs_sb) {
Igor Mammedove6ab1582008-01-11 01:49:48 +0000200#ifdef CONFIG_CIFS_DFS_UPCALL
201 if (cifs_sb->mountdata) {
202 kfree(cifs_sb->mountdata);
203 cifs_sb->mountdata = NULL;
204 }
205#endif
Thomas Gleixner6d729e42009-08-16 21:05:08 +0000206 unload_nls(cifs_sb->local_nls);
Jens Axboe8044f7f2010-04-22 12:09:48 +0200207 bdi_destroy(&cifs_sb->bdi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 kfree(cifs_sb);
209 }
210 return rc;
211}
212
213static void
214cifs_put_super(struct super_block *sb)
215{
216 int rc = 0;
217 struct cifs_sb_info *cifs_sb;
218
Joe Perchesb6b38f72010-04-21 03:50:45 +0000219 cFYI(1, "In cifs_put_super");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 cifs_sb = CIFS_SB(sb);
Steve French4523cc32007-04-30 20:13:06 +0000221 if (cifs_sb == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000222 cFYI(1, "Empty cifs superblock info passed to unmount");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 return;
224 }
Christoph Hellwig6cfd0142009-05-05 15:40:36 +0200225
Steve French790fe572007-07-07 19:25:05 +0000226 rc = cifs_umount(sb, cifs_sb);
Steve Frenchad7a2922008-02-07 23:25:02 +0000227 if (rc)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000228 cERROR(1, "cifs_umount failed with return code %d", rc);
Igor Mammedove6ab1582008-01-11 01:49:48 +0000229#ifdef CONFIG_CIFS_DFS_UPCALL
230 if (cifs_sb->mountdata) {
231 kfree(cifs_sb->mountdata);
232 cifs_sb->mountdata = NULL;
233 }
234#endif
235
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 unload_nls(cifs_sb->local_nls);
Jens Axboe8044f7f2010-04-22 12:09:48 +0200237 bdi_destroy(&cifs_sb->bdi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 kfree(cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239}
240
241static int
David Howells726c3342006-06-23 02:02:58 -0700242cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243{
David Howells726c3342006-06-23 02:02:58 -0700244 struct super_block *sb = dentry->d_sb;
Steve French39da9842008-04-28 04:04:34 +0000245 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700246 struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
Steve Frenchc81156d2005-04-28 22:41:07 -0700247 int rc = -EOPNOTSUPP;
Steve French39da9842008-04-28 04:04:34 +0000248 int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249
250 xid = GetXid();
251
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 buf->f_type = CIFS_MAGIC_NUMBER;
253
Steve French39da9842008-04-28 04:04:34 +0000254 /*
255 * PATH_MAX may be too long - it would presumably be total path,
256 * but note that some servers (includinng Samba 3) have a shorter
257 * maximum path.
258 *
259 * Instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO.
260 */
261 buf->f_namelen = PATH_MAX;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 buf->f_files = 0; /* undefined */
263 buf->f_ffree = 0; /* unlimited */
264
Steve French39da9842008-04-28 04:04:34 +0000265 /*
266 * We could add a second check for a QFS Unix capability bit
267 */
268 if ((tcon->ses->capabilities & CAP_UNIX) &&
269 (CIFS_POSIX_EXTENSIONS & le64_to_cpu(tcon->fsUnixInfo.Capability)))
270 rc = CIFSSMBQFSPosixInfo(xid, tcon, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
Steve French39da9842008-04-28 04:04:34 +0000272 /*
273 * Only need to call the old QFSInfo if failed on newer one,
274 * e.g. by OS/2.
275 **/
276 if (rc && (tcon->ses->capabilities & CAP_NT_SMBS))
277 rc = CIFSSMBQFSInfo(xid, tcon, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
Steve French39da9842008-04-28 04:04:34 +0000279 /*
280 * Some old Windows servers also do not support level 103, retry with
281 * older level one if old server failed the previous call or we
282 * bypassed it because we detected that this was an older LANMAN sess
283 */
Steve French4523cc32007-04-30 20:13:06 +0000284 if (rc)
Steve French39da9842008-04-28 04:04:34 +0000285 rc = SMBOldQFSInfo(xid, tcon, buf);
286
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 FreeXid(xid);
Steve French39da9842008-04-28 04:04:34 +0000288 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289}
290
Nick Pigginb74c79e2011-01-07 17:49:58 +1100291static int cifs_permission(struct inode *inode, int mask, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292{
293 struct cifs_sb_info *cifs_sb;
294
Nick Pigginb74c79e2011-01-07 17:49:58 +1100295 if (flags & IPERM_FLAG_RCU)
296 return -ECHILD;
297
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 cifs_sb = CIFS_SB(inode->i_sb);
299
Miklos Szeredif696a362008-07-31 13:41:58 +0200300 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
301 if ((mask & MAY_EXEC) && !execute_ok(inode))
302 return -EACCES;
303 else
304 return 0;
305 } else /* file mode might have been restricted at mount time
Steve French50c2f752007-07-13 00:33:32 +0000306 on the client (above and beyond ACL on servers) for
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 servers which do not support setting and viewing mode bits,
Steve French50c2f752007-07-13 00:33:32 +0000308 so allowing client to check permissions is useful */
Nick Pigginb74c79e2011-01-07 17:49:58 +1100309 return generic_permission(inode, mask, flags, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310}
311
Christoph Lametere18b8902006-12-06 20:33:20 -0800312static struct kmem_cache *cifs_inode_cachep;
313static struct kmem_cache *cifs_req_cachep;
314static struct kmem_cache *cifs_mid_cachep;
Christoph Lametere18b8902006-12-06 20:33:20 -0800315static struct kmem_cache *cifs_sm_req_cachep;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316mempool_t *cifs_sm_req_poolp;
317mempool_t *cifs_req_poolp;
318mempool_t *cifs_mid_poolp;
319
320static struct inode *
321cifs_alloc_inode(struct super_block *sb)
322{
323 struct cifsInodeInfo *cifs_inode;
Christoph Lametere94b1762006-12-06 20:33:17 -0800324 cifs_inode = kmem_cache_alloc(cifs_inode_cachep, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 if (!cifs_inode)
326 return NULL;
327 cifs_inode->cifsAttrs = 0x20; /* default */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 cifs_inode->time = 0;
329 /* Until the file is open and we have gotten oplock
330 info back from the server, can not assume caching of
331 file data or metadata */
Pavel Shilovskyc6723622010-11-03 10:58:57 +0300332 cifs_set_oplock_level(cifs_inode, 0);
Jeff Layton9a8165f2008-10-17 21:03:20 -0400333 cifs_inode->delete_pending = false;
Jeff Laytondf2cf172010-02-12 07:44:16 -0500334 cifs_inode->invalid_mapping = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400336 cifs_inode->server_eof = 0;
Jeff Layton20054bd2011-01-07 11:30:27 -0500337 cifs_inode->uniqueid = 0;
338 cifs_inode->createtime = 0;
Steve French50c2f752007-07-13 00:33:32 +0000339
Steve French1b2b2122007-02-17 04:30:54 +0000340 /* Can not set i_flags here - they get immediately overwritten
341 to zero by the VFS */
342/* cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 INIT_LIST_HEAD(&cifs_inode->openFileList);
344 return &cifs_inode->vfs_inode;
345}
346
Nick Pigginfa0d7e3d2011-01-07 17:49:49 +1100347static void cifs_i_callback(struct rcu_head *head)
348{
349 struct inode *inode = container_of(head, struct inode, i_rcu);
350 INIT_LIST_HEAD(&inode->i_dentry);
351 kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
352}
353
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354static void
355cifs_destroy_inode(struct inode *inode)
356{
Nick Pigginfa0d7e3d2011-01-07 17:49:49 +1100357 call_rcu(&inode->i_rcu, cifs_i_callback);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358}
359
Jeff Layton61f98ff2009-06-11 10:27:32 -0400360static void
Al Virob57922d2010-06-07 14:34:48 -0400361cifs_evict_inode(struct inode *inode)
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530362{
Al Virob57922d2010-06-07 14:34:48 -0400363 truncate_inode_pages(&inode->i_data, 0);
364 end_writeback(inode);
Suresh Jayaraman9451a9a2010-07-05 18:12:45 +0530365 cifs_fscache_release_inode_cookie(inode);
366}
367
368static void
Jeff Layton61f98ff2009-06-11 10:27:32 -0400369cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
370{
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300371 struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr;
372 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr;
373
Jeff Layton61f98ff2009-06-11 10:27:32 -0400374 seq_printf(s, ",addr=");
375
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300376 switch (server->dstaddr.ss_family) {
Jeff Layton61f98ff2009-06-11 10:27:32 -0400377 case AF_INET:
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300378 seq_printf(s, "%pI4", &sa->sin_addr.s_addr);
Jeff Layton61f98ff2009-06-11 10:27:32 -0400379 break;
380 case AF_INET6:
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300381 seq_printf(s, "%pI6", &sa6->sin6_addr.s6_addr);
382 if (sa6->sin6_scope_id)
383 seq_printf(s, "%%%u", sa6->sin6_scope_id);
Jeff Layton61f98ff2009-06-11 10:27:32 -0400384 break;
385 default:
386 seq_printf(s, "(unknown)");
387 }
388}
389
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390/*
391 * cifs_show_options() is for displaying mount options in /proc/mounts.
392 * Not all settable options are displayed but most of the important
393 * ones are.
394 */
395static int
396cifs_show_options(struct seq_file *s, struct vfsmount *m)
397{
Jeff Layton8e047d02009-08-28 10:11:10 -0400398 struct cifs_sb_info *cifs_sb = CIFS_SB(m->mnt_sb);
Jeff Layton0d424ad2010-09-20 16:01:35 -0700399 struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
Ben Greear3eb9a882010-09-01 17:06:02 -0700400 struct sockaddr *srcaddr;
401 srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402
Jeff Layton8e047d02009-08-28 10:11:10 -0400403 seq_printf(s, ",unc=%s", tcon->treeName);
Jeff Layton29e07c82010-09-29 19:51:12 -0400404
405 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)
406 seq_printf(s, ",multiuser");
Steve French8727c8a2011-02-25 01:11:56 -0600407 else if (tcon->ses->user_name)
408 seq_printf(s, ",username=%s", tcon->ses->user_name);
Jeff Layton29e07c82010-09-29 19:51:12 -0400409
Jeff Layton8616e0f2009-06-11 10:27:28 -0400410 if (tcon->ses->domainName)
411 seq_printf(s, ",domain=%s", tcon->ses->domainName);
412
Ben Greear3eb9a882010-09-01 17:06:02 -0700413 if (srcaddr->sa_family != AF_UNSPEC) {
414 struct sockaddr_in *saddr4;
415 struct sockaddr_in6 *saddr6;
416 saddr4 = (struct sockaddr_in *)srcaddr;
417 saddr6 = (struct sockaddr_in6 *)srcaddr;
418 if (srcaddr->sa_family == AF_INET6)
419 seq_printf(s, ",srcaddr=%pI6c",
420 &saddr6->sin6_addr);
421 else if (srcaddr->sa_family == AF_INET)
422 seq_printf(s, ",srcaddr=%pI4",
423 &saddr4->sin_addr.s_addr);
424 else
425 seq_printf(s, ",srcaddr=BAD-AF:%i",
426 (int)(srcaddr->sa_family));
427 }
428
Jeff Layton8616e0f2009-06-11 10:27:28 -0400429 seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
Jeff Layton340481a32009-06-11 10:27:29 -0400430 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
431 seq_printf(s, ",forceuid");
Jeff Layton4486d6e2009-08-03 12:45:10 -0400432 else
433 seq_printf(s, ",noforceuid");
Jeff Layton340481a32009-06-11 10:27:29 -0400434
Jeff Layton8616e0f2009-06-11 10:27:28 -0400435 seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
Jeff Layton340481a32009-06-11 10:27:29 -0400436 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
437 seq_printf(s, ",forcegid");
Jeff Layton4486d6e2009-08-03 12:45:10 -0400438 else
439 seq_printf(s, ",noforcegid");
Jeff Layton8616e0f2009-06-11 10:27:28 -0400440
Jeff Layton61f98ff2009-06-11 10:27:32 -0400441 cifs_show_address(s, tcon->ses->server);
Jeff Layton8616e0f2009-06-11 10:27:28 -0400442
443 if (!tcon->unix_ext)
444 seq_printf(s, ",file_mode=0%o,dir_mode=0%o",
Steve French2b280fa2008-05-17 03:12:45 +0000445 cifs_sb->mnt_file_mode,
446 cifs_sb->mnt_dir_mode);
Jeff Layton8616e0f2009-06-11 10:27:28 -0400447 if (tcon->seal)
448 seq_printf(s, ",seal");
449 if (tcon->nocase)
450 seq_printf(s, ",nocase");
451 if (tcon->retry)
452 seq_printf(s, ",hard");
453 if (cifs_sb->prepath)
454 seq_printf(s, ",prepath=%s", cifs_sb->prepath);
455 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
456 seq_printf(s, ",posixpaths");
457 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
458 seq_printf(s, ",setuids");
459 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
460 seq_printf(s, ",serverino");
461 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
462 seq_printf(s, ",directio");
463 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
464 seq_printf(s, ",nouser_xattr");
465 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
466 seq_printf(s, ",mapchars");
467 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
468 seq_printf(s, ",sfu");
469 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
470 seq_printf(s, ",nobrl");
471 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
472 seq_printf(s, ",cifsacl");
473 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
474 seq_printf(s, ",dynperm");
475 if (m->mnt_sb->s_flags & MS_POSIXACL)
476 seq_printf(s, ",acl");
Stefan Metzmacher736a3322010-07-30 14:56:00 +0200477 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
478 seq_printf(s, ",mfsymlinks");
Suresh Jayaraman476428f2010-11-24 17:49:07 +0530479 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE)
480 seq_printf(s, ",fsc");
Steve French2b280fa2008-05-17 03:12:45 +0000481
Jeff Layton8616e0f2009-06-11 10:27:28 -0400482 seq_printf(s, ",rsize=%d", cifs_sb->rsize);
483 seq_printf(s, ",wsize=%d", cifs_sb->wsize);
Suresh Jayaraman6d20e842010-12-01 14:42:28 +0530484 /* convert actimeo and display it in seconds */
485 seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);
Jeff Layton8616e0f2009-06-11 10:27:28 -0400486
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 return 0;
488}
489
Al Viro42faad92008-04-24 07:21:56 -0400490static void cifs_umount_begin(struct super_block *sb)
Steve French68058e72005-10-10 10:34:22 -0700491{
Al Viro42faad92008-04-24 07:21:56 -0400492 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French50c2f752007-07-13 00:33:32 +0000493 struct cifsTconInfo *tcon;
Steve French68058e72005-10-10 10:34:22 -0700494
Steve French4523cc32007-04-30 20:13:06 +0000495 if (cifs_sb == NULL)
Steve French9e2e85f2005-10-10 14:28:38 -0700496 return;
497
Jeff Layton0d424ad2010-09-20 16:01:35 -0700498 tcon = cifs_sb_master_tcon(cifs_sb);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500499
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530500 spin_lock(&cifs_tcp_ses_lock);
Steve Frenchad8034f2009-06-26 03:25:49 +0000501 if ((tcon->tc_count > 1) || (tcon->tidStatus == CifsExiting)) {
502 /* we have other mounts to same share or we have
503 already tried to force umount this and woken up
504 all waiting network requests, nothing to do */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530505 spin_unlock(&cifs_tcp_ses_lock);
Steve Frenchad8034f2009-06-26 03:25:49 +0000506 return;
507 } else if (tcon->tc_count == 1)
Steve French5e1253b2005-10-10 14:06:37 -0700508 tcon->tidStatus = CifsExiting;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530509 spin_unlock(&cifs_tcp_ses_lock);
Steve French5e1253b2005-10-10 14:06:37 -0700510
Steve French3a5ff612006-07-14 22:37:11 +0000511 /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
Steve French7b7abfe2005-11-09 15:21:09 -0800512 /* cancel_notify_requests(tcon); */
Steve French50c2f752007-07-13 00:33:32 +0000513 if (tcon->ses && tcon->ses->server) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000514 cFYI(1, "wake up tasks now - umount begin not complete");
Steve French9e2e85f2005-10-10 14:28:38 -0700515 wake_up_all(&tcon->ses->server->request_q);
Steve French6ab16d22005-11-29 20:55:11 -0800516 wake_up_all(&tcon->ses->server->response_q);
517 msleep(1); /* yield */
518 /* we have to kick the requests once more */
519 wake_up_all(&tcon->ses->server->response_q);
520 msleep(1);
Steve French5e1253b2005-10-10 14:06:37 -0700521 }
Steve French68058e72005-10-10 10:34:22 -0700522
523 return;
524}
Steve French68058e72005-10-10 10:34:22 -0700525
Steve Frenchbf97d282006-09-28 21:34:06 +0000526#ifdef CONFIG_CIFS_STATS2
527static int cifs_show_stats(struct seq_file *s, struct vfsmount *mnt)
528{
529 /* BB FIXME */
530 return 0;
531}
532#endif
533
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534static int cifs_remount(struct super_block *sb, int *flags, char *data)
535{
536 *flags |= MS_NODIRATIME;
537 return 0;
538}
539
Al Viro45321ac2010-06-07 13:43:19 -0400540static int cifs_drop_inode(struct inode *inode)
Jeff Layton12420ac2010-06-01 14:47:40 -0400541{
542 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
543
Al Viro45321ac2010-06-07 13:43:19 -0400544 /* no serverino => unconditional eviction */
545 return !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) ||
546 generic_drop_inode(inode);
Jeff Layton12420ac2010-06-01 14:47:40 -0400547}
548
Josef 'Jeff' Sipekee9b6d62007-02-12 00:55:41 -0800549static const struct super_operations cifs_super_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 .put_super = cifs_put_super,
551 .statfs = cifs_statfs,
552 .alloc_inode = cifs_alloc_inode,
553 .destroy_inode = cifs_destroy_inode,
Jeff Layton12420ac2010-06-01 14:47:40 -0400554 .drop_inode = cifs_drop_inode,
Al Virob57922d2010-06-07 14:34:48 -0400555 .evict_inode = cifs_evict_inode,
Jeff Layton12420ac2010-06-01 14:47:40 -0400556/* .delete_inode = cifs_delete_inode, */ /* Do not need above
557 function unless later we add lazy close of inodes or unless the
Steve French50c2f752007-07-13 00:33:32 +0000558 kernel forgets to call us with the same number of releases (closes)
559 as opens */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 .show_options = cifs_show_options,
Steve French7b7abfe2005-11-09 15:21:09 -0800561 .umount_begin = cifs_umount_begin,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 .remount_fs = cifs_remount,
Steve Frenchbf97d282006-09-28 21:34:06 +0000563#ifdef CONFIG_CIFS_STATS2
Steve Frenchf46d3e12006-09-30 01:08:55 +0000564 .show_stats = cifs_show_stats,
Steve Frenchbf97d282006-09-28 21:34:06 +0000565#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566};
567
Al Virod753ed92010-07-26 12:52:33 +0400568static struct dentry *
569cifs_do_mount(struct file_system_type *fs_type,
570 int flags, const char *dev_name, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571{
572 int rc;
Jan Blunckdb719222010-08-15 22:51:10 +0200573 struct super_block *sb;
574
Jan Blunckdb719222010-08-15 22:51:10 +0200575 sb = sget(fs_type, NULL, set_anon_super, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576
Joe Perchesb6b38f72010-04-21 03:50:45 +0000577 cFYI(1, "Devname: %s flags: %d ", dev_name, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578
Jan Blunckb0991aa2010-02-24 13:25:29 +0100579 if (IS_ERR(sb))
Al Virod753ed92010-07-26 12:52:33 +0400580 return ERR_CAST(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581
582 sb->s_flags = flags;
583
Theodore Ts'o9b04c992006-03-24 03:15:10 -0800584 rc = cifs_read_super(sb, data, dev_name, flags & MS_SILENT ? 1 : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 if (rc) {
Al Viro6f5bbff2009-05-06 01:34:22 -0400586 deactivate_locked_super(sb);
Al Virod753ed92010-07-26 12:52:33 +0400587 return ERR_PTR(rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 }
589 sb->s_flags |= MS_ACTIVE;
Al Virod753ed92010-07-26 12:52:33 +0400590 return dget(sb->s_root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591}
592
Badari Pulavarty027445c2006-09-30 23:28:46 -0700593static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
594 unsigned long nr_segs, loff_t pos)
Steve French87c89dd2005-11-17 17:03:00 -0800595{
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -0800596 struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
Steve French87c89dd2005-11-17 17:03:00 -0800597 ssize_t written;
Pavel Shilovsky72432ff2011-01-24 14:16:35 -0500598 int rc;
Steve French87c89dd2005-11-17 17:03:00 -0800599
Badari Pulavarty027445c2006-09-30 23:28:46 -0700600 written = generic_file_aio_write(iocb, iov, nr_segs, pos);
Pavel Shilovsky72432ff2011-01-24 14:16:35 -0500601
602 if (CIFS_I(inode)->clientCanCacheAll)
603 return written;
604
605 rc = filemap_fdatawrite(inode->i_mapping);
606 if (rc)
607 cFYI(1, "cifs_file_aio_write: %d rc on %p inode", rc, inode);
608
Steve French87c89dd2005-11-17 17:03:00 -0800609 return written;
610}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
Steve Frenchc32a0b62006-01-12 14:41:28 -0800612static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
613{
614 /* origin == SEEK_END => we must revalidate the cached file length */
Steve French0889a942006-09-23 22:11:07 +0000615 if (origin == SEEK_END) {
Pavel Shilovsky6feb9892011-04-07 18:18:11 +0400616 int rc;
617 struct inode *inode = file->f_path.dentry->d_inode;
Steve French030e9d82007-02-01 04:27:59 +0000618
Pavel Shilovsky6feb9892011-04-07 18:18:11 +0400619 /*
620 * We need to be sure that all dirty pages are written and the
621 * server has the newest file length.
622 */
623 if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping &&
624 inode->i_mapping->nrpages != 0) {
625 rc = filemap_fdatawait(inode->i_mapping);
626 mapping_set_error(inode->i_mapping, rc);
627 return rc;
628 }
629 /*
630 * Some applications poll for the file length in this strange
631 * way so we must seek to end on non-oplocked files by
632 * setting the revalidate time to zero.
633 */
634 CIFS_I(inode)->time = 0;
Steve French030e9d82007-02-01 04:27:59 +0000635
Pavel Shilovsky6feb9892011-04-07 18:18:11 +0400636 rc = cifs_revalidate_file_attr(file);
637 if (rc < 0)
638 return (loff_t)rc;
Steve Frenchc32a0b62006-01-12 14:41:28 -0800639 }
Andi Kleen9465efc2008-06-27 11:05:24 +0200640 return generic_file_llseek_unlocked(file, offset, origin);
Steve Frenchc32a0b62006-01-12 14:41:28 -0800641}
642
Steve French84210e92008-10-23 04:42:37 +0000643static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
644{
Arnd Bergmannb89f4322010-09-18 15:09:31 +0200645 /* note that this is called by vfs setlease with lock_flocks held
646 to protect *lease from going away */
Steve French84210e92008-10-23 04:42:37 +0000647 struct inode *inode = file->f_path.dentry->d_inode;
Jeff Laytonba00ba62010-09-20 16:01:31 -0700648 struct cifsFileInfo *cfile = file->private_data;
Steve French84210e92008-10-23 04:42:37 +0000649
650 if (!(S_ISREG(inode->i_mode)))
651 return -EINVAL;
652
653 /* check if file is oplocked */
654 if (((arg == F_RDLCK) &&
655 (CIFS_I(inode)->clientCanCacheRead)) ||
656 ((arg == F_WRLCK) &&
657 (CIFS_I(inode)->clientCanCacheAll)))
658 return generic_setlease(file, arg, lease);
Jeff Layton13cfb732010-09-29 19:51:11 -0400659 else if (tlink_tcon(cfile->tlink)->local_lease &&
660 !CIFS_I(inode)->clientCanCacheRead)
Steve French84210e92008-10-23 04:42:37 +0000661 /* If the server claims to support oplock on this
662 file, then we still need to check oplock even
663 if the local_lease mount option is set, but there
664 are servers which do not support oplock for which
665 this mount option may be useful if the user
666 knows that the file won't be changed on the server
667 by anyone else */
668 return generic_setlease(file, arg, lease);
Christoph Hellwig51ee4b82010-10-31 08:35:10 -0400669 else
Steve French84210e92008-10-23 04:42:37 +0000670 return -EAGAIN;
671}
Steve French84210e92008-10-23 04:42:37 +0000672
Igor Mammedove6ab1582008-01-11 01:49:48 +0000673struct file_system_type cifs_fs_type = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 .owner = THIS_MODULE,
675 .name = "cifs",
Al Virod753ed92010-07-26 12:52:33 +0400676 .mount = cifs_do_mount,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 .kill_sb = kill_anon_super,
678 /* .fs_flags */
679};
Arjan van de Ven754661f2007-02-12 00:55:38 -0800680const struct inode_operations cifs_dir_inode_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 .create = cifs_create,
682 .lookup = cifs_lookup,
683 .getattr = cifs_getattr,
684 .unlink = cifs_unlink,
685 .link = cifs_hardlink,
686 .mkdir = cifs_mkdir,
687 .rmdir = cifs_rmdir,
688 .rename = cifs_rename,
689 .permission = cifs_permission,
690/* revalidate:cifs_revalidate, */
691 .setattr = cifs_setattr,
692 .symlink = cifs_symlink,
693 .mknod = cifs_mknod,
694#ifdef CONFIG_CIFS_XATTR
695 .setxattr = cifs_setxattr,
696 .getxattr = cifs_getxattr,
697 .listxattr = cifs_listxattr,
698 .removexattr = cifs_removexattr,
699#endif
700};
701
Arjan van de Ven754661f2007-02-12 00:55:38 -0800702const struct inode_operations cifs_file_inode_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703/* revalidate:cifs_revalidate, */
704 .setattr = cifs_setattr,
705 .getattr = cifs_getattr, /* do we need this anymore? */
706 .rename = cifs_rename,
707 .permission = cifs_permission,
708#ifdef CONFIG_CIFS_XATTR
709 .setxattr = cifs_setxattr,
710 .getxattr = cifs_getxattr,
711 .listxattr = cifs_listxattr,
712 .removexattr = cifs_removexattr,
Steve French50c2f752007-07-13 00:33:32 +0000713#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714};
715
Arjan van de Ven754661f2007-02-12 00:55:38 -0800716const struct inode_operations cifs_symlink_inode_ops = {
Steve French50c2f752007-07-13 00:33:32 +0000717 .readlink = generic_readlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 .follow_link = cifs_follow_link,
719 .put_link = cifs_put_link,
720 .permission = cifs_permission,
721 /* BB add the following two eventually */
722 /* revalidate: cifs_revalidate,
723 setattr: cifs_notify_change, *//* BB do we need notify change */
724#ifdef CONFIG_CIFS_XATTR
725 .setxattr = cifs_setxattr,
726 .getxattr = cifs_getxattr,
727 .listxattr = cifs_listxattr,
728 .removexattr = cifs_removexattr,
Steve French50c2f752007-07-13 00:33:32 +0000729#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730};
731
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800732const struct file_operations cifs_file_ops = {
Steve French87c89dd2005-11-17 17:03:00 -0800733 .read = do_sync_read,
734 .write = do_sync_write,
Steve French87c89dd2005-11-17 17:03:00 -0800735 .aio_read = generic_file_aio_read,
736 .aio_write = cifs_file_aio_write,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 .open = cifs_open,
738 .release = cifs_close,
739 .lock = cifs_lock,
740 .fsync = cifs_fsync,
741 .flush = cifs_flush,
742 .mmap = cifs_file_mmap,
Jens Axboe5ffc4ef2007-06-01 11:49:19 +0200743 .splice_read = generic_file_splice_read,
Steve Frenchc32a0b62006-01-12 14:41:28 -0800744 .llseek = cifs_llseek,
Steve Frenchc67593a2005-04-28 22:41:04 -0700745#ifdef CONFIG_CIFS_POSIX
Steve Frenchf9ddcca2008-05-15 05:51:55 +0000746 .unlocked_ioctl = cifs_ioctl,
Steve Frenchc67593a2005-04-28 22:41:04 -0700747#endif /* CONFIG_CIFS_POSIX */
Steve French84210e92008-10-23 04:42:37 +0000748 .setlease = cifs_setlease,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749};
750
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +0300751const struct file_operations cifs_file_strict_ops = {
752 .read = do_sync_read,
753 .write = do_sync_write,
Pavel Shilovskya70307e2010-12-14 11:50:41 +0300754 .aio_read = cifs_strict_readv,
Pavel Shilovsky72432ff2011-01-24 14:16:35 -0500755 .aio_write = cifs_strict_writev,
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +0300756 .open = cifs_open,
757 .release = cifs_close,
758 .lock = cifs_lock,
759 .fsync = cifs_strict_fsync,
760 .flush = cifs_flush,
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +0300761 .mmap = cifs_file_strict_mmap,
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +0300762 .splice_read = generic_file_splice_read,
763 .llseek = cifs_llseek,
764#ifdef CONFIG_CIFS_POSIX
765 .unlocked_ioctl = cifs_ioctl,
766#endif /* CONFIG_CIFS_POSIX */
767 .setlease = cifs_setlease,
768};
769
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800770const struct file_operations cifs_file_direct_ops = {
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +0300771 /* BB reevaluate whether they can be done with directio, no cache */
772 .read = do_sync_read,
773 .write = do_sync_write,
774 .aio_read = cifs_user_readv,
775 .aio_write = cifs_user_writev,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 .open = cifs_open,
777 .release = cifs_close,
778 .lock = cifs_lock,
779 .fsync = cifs_fsync,
780 .flush = cifs_flush,
Steve Frencha994b8f2009-12-07 05:44:46 +0000781 .mmap = cifs_file_mmap,
Jens Axboe5ffc4ef2007-06-01 11:49:19 +0200782 .splice_read = generic_file_splice_read,
Steve Frenchc67593a2005-04-28 22:41:04 -0700783#ifdef CONFIG_CIFS_POSIX
Steve Frenchf9ddcca2008-05-15 05:51:55 +0000784 .unlocked_ioctl = cifs_ioctl,
Steve Frenchc67593a2005-04-28 22:41:04 -0700785#endif /* CONFIG_CIFS_POSIX */
Steve Frenchc32a0b62006-01-12 14:41:28 -0800786 .llseek = cifs_llseek,
Steve French84210e92008-10-23 04:42:37 +0000787 .setlease = cifs_setlease,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788};
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +0300789
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800790const struct file_operations cifs_file_nobrl_ops = {
Steve French87c89dd2005-11-17 17:03:00 -0800791 .read = do_sync_read,
792 .write = do_sync_write,
Steve French87c89dd2005-11-17 17:03:00 -0800793 .aio_read = generic_file_aio_read,
794 .aio_write = cifs_file_aio_write,
795 .open = cifs_open,
796 .release = cifs_close,
797 .fsync = cifs_fsync,
798 .flush = cifs_flush,
799 .mmap = cifs_file_mmap,
Jens Axboe5ffc4ef2007-06-01 11:49:19 +0200800 .splice_read = generic_file_splice_read,
Steve Frenchc32a0b62006-01-12 14:41:28 -0800801 .llseek = cifs_llseek,
Steve French8b94bcb2005-11-11 11:41:00 -0800802#ifdef CONFIG_CIFS_POSIX
Steve Frenchf9ddcca2008-05-15 05:51:55 +0000803 .unlocked_ioctl = cifs_ioctl,
Steve French8b94bcb2005-11-11 11:41:00 -0800804#endif /* CONFIG_CIFS_POSIX */
Steve French84210e92008-10-23 04:42:37 +0000805 .setlease = cifs_setlease,
Steve French8b94bcb2005-11-11 11:41:00 -0800806};
807
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +0300808const struct file_operations cifs_file_strict_nobrl_ops = {
809 .read = do_sync_read,
810 .write = do_sync_write,
Pavel Shilovskya70307e2010-12-14 11:50:41 +0300811 .aio_read = cifs_strict_readv,
Pavel Shilovsky72432ff2011-01-24 14:16:35 -0500812 .aio_write = cifs_strict_writev,
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +0300813 .open = cifs_open,
814 .release = cifs_close,
815 .fsync = cifs_strict_fsync,
816 .flush = cifs_flush,
Pavel Shilovsky7a6a19b2010-12-14 11:29:51 +0300817 .mmap = cifs_file_strict_mmap,
Pavel Shilovsky8be7e6b2010-12-12 13:11:13 +0300818 .splice_read = generic_file_splice_read,
819 .llseek = cifs_llseek,
820#ifdef CONFIG_CIFS_POSIX
821 .unlocked_ioctl = cifs_ioctl,
822#endif /* CONFIG_CIFS_POSIX */
823 .setlease = cifs_setlease,
824};
825
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800826const struct file_operations cifs_file_direct_nobrl_ops = {
Pavel Shilovsky0b81c1c2011-03-10 10:11:05 +0300827 /* BB reevaluate whether they can be done with directio, no cache */
828 .read = do_sync_read,
829 .write = do_sync_write,
830 .aio_read = cifs_user_readv,
831 .aio_write = cifs_user_writev,
Steve French87c89dd2005-11-17 17:03:00 -0800832 .open = cifs_open,
833 .release = cifs_close,
834 .fsync = cifs_fsync,
835 .flush = cifs_flush,
Pavel Shilovsky810627a2010-03-27 02:00:49 +0000836 .mmap = cifs_file_mmap,
Jens Axboe5ffc4ef2007-06-01 11:49:19 +0200837 .splice_read = generic_file_splice_read,
Steve French8b94bcb2005-11-11 11:41:00 -0800838#ifdef CONFIG_CIFS_POSIX
Steve Frenchf9ddcca2008-05-15 05:51:55 +0000839 .unlocked_ioctl = cifs_ioctl,
Steve French8b94bcb2005-11-11 11:41:00 -0800840#endif /* CONFIG_CIFS_POSIX */
Steve Frenchc32a0b62006-01-12 14:41:28 -0800841 .llseek = cifs_llseek,
Steve French84210e92008-10-23 04:42:37 +0000842 .setlease = cifs_setlease,
Steve French8b94bcb2005-11-11 11:41:00 -0800843};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800845const struct file_operations cifs_dir_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 .readdir = cifs_readdir,
847 .release = cifs_closedir,
848 .read = generic_read_dir,
Steve Frenchf9ddcca2008-05-15 05:51:55 +0000849 .unlocked_ioctl = cifs_ioctl,
Christoph Hellwig3222a3e2008-09-03 21:53:01 +0200850 .llseek = generic_file_llseek,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851};
852
853static void
Alexey Dobriyan51cc5062008-07-25 19:45:34 -0700854cifs_init_once(void *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855{
856 struct cifsInodeInfo *cifsi = inode;
857
Christoph Lametera35afb82007-05-16 22:10:57 -0700858 inode_init_once(&cifsi->vfs_inode);
859 INIT_LIST_HEAD(&cifsi->lockList);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860}
861
862static int
863cifs_init_inodecache(void)
864{
865 cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
Steve French26f57362007-08-30 22:09:15 +0000866 sizeof(struct cifsInodeInfo),
Paul Jacksonfffb60f2006-03-24 03:16:06 -0800867 0, (SLAB_RECLAIM_ACCOUNT|
868 SLAB_MEM_SPREAD),
Paul Mundt20c2df82007-07-20 10:11:58 +0900869 cifs_init_once);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 if (cifs_inode_cachep == NULL)
871 return -ENOMEM;
872
873 return 0;
874}
875
876static void
877cifs_destroy_inodecache(void)
878{
Alexey Dobriyan1a1d92c2006-09-27 01:49:40 -0700879 kmem_cache_destroy(cifs_inode_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880}
881
882static int
883cifs_init_request_bufs(void)
884{
Steve French4523cc32007-04-30 20:13:06 +0000885 if (CIFSMaxBufSize < 8192) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 /* Buffer size can not be smaller than 2 * PATH_MAX since maximum
887 Unicode path name has to fit in any SMB/CIFS path based frames */
888 CIFSMaxBufSize = 8192;
889 } else if (CIFSMaxBufSize > 1024*127) {
890 CIFSMaxBufSize = 1024 * 127;
891 } else {
892 CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/
893 }
Joe Perchesb6b38f72010-04-21 03:50:45 +0000894/* cERROR(1, "CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize); */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 cifs_req_cachep = kmem_cache_create("cifs_request",
896 CIFSMaxBufSize +
897 MAX_CIFS_HDR_SIZE, 0,
Paul Mundt20c2df82007-07-20 10:11:58 +0900898 SLAB_HWCACHE_ALIGN, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 if (cifs_req_cachep == NULL)
900 return -ENOMEM;
901
Steve French4523cc32007-04-30 20:13:06 +0000902 if (cifs_min_rcv < 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 cifs_min_rcv = 1;
904 else if (cifs_min_rcv > 64) {
905 cifs_min_rcv = 64;
Joe Perchesb6b38f72010-04-21 03:50:45 +0000906 cERROR(1, "cifs_min_rcv set to maximum (64)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 }
908
Matthew Dobson93d23412006-03-26 01:37:50 -0800909 cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv,
910 cifs_req_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911
Steve French4523cc32007-04-30 20:13:06 +0000912 if (cifs_req_poolp == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 kmem_cache_destroy(cifs_req_cachep);
914 return -ENOMEM;
915 }
Steve Frenchec637e32005-12-12 20:53:18 -0800916 /* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 almost all handle based requests (but not write response, nor is it
918 sufficient for path based requests). A smaller size would have
Steve French50c2f752007-07-13 00:33:32 +0000919 been more efficient (compacting multiple slab items on one 4k page)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 for the case in which debug was on, but this larger size allows
921 more SMBs to use small buffer alloc and is still much more
Steve French6dc0f872007-07-06 23:13:06 +0000922 efficient to alloc 1 per page off the slab compared to 17K (5page)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 alloc of large cifs buffers even when page debugging is on */
924 cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq",
Steve French6dc0f872007-07-06 23:13:06 +0000925 MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN,
Paul Mundt20c2df82007-07-20 10:11:58 +0900926 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 if (cifs_sm_req_cachep == NULL) {
928 mempool_destroy(cifs_req_poolp);
929 kmem_cache_destroy(cifs_req_cachep);
Steve French6dc0f872007-07-06 23:13:06 +0000930 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 }
932
Steve French4523cc32007-04-30 20:13:06 +0000933 if (cifs_min_small < 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 cifs_min_small = 2;
935 else if (cifs_min_small > 256) {
936 cifs_min_small = 256;
Joe Perchesb6b38f72010-04-21 03:50:45 +0000937 cFYI(1, "cifs_min_small set to maximum (256)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 }
939
Matthew Dobson93d23412006-03-26 01:37:50 -0800940 cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small,
941 cifs_sm_req_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942
Steve French4523cc32007-04-30 20:13:06 +0000943 if (cifs_sm_req_poolp == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 mempool_destroy(cifs_req_poolp);
945 kmem_cache_destroy(cifs_req_cachep);
946 kmem_cache_destroy(cifs_sm_req_cachep);
947 return -ENOMEM;
948 }
949
950 return 0;
951}
952
953static void
954cifs_destroy_request_bufs(void)
955{
956 mempool_destroy(cifs_req_poolp);
Alexey Dobriyan1a1d92c2006-09-27 01:49:40 -0700957 kmem_cache_destroy(cifs_req_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 mempool_destroy(cifs_sm_req_poolp);
Alexey Dobriyan1a1d92c2006-09-27 01:49:40 -0700959 kmem_cache_destroy(cifs_sm_req_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960}
961
962static int
963cifs_init_mids(void)
964{
965 cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
Steve French26f57362007-08-30 22:09:15 +0000966 sizeof(struct mid_q_entry), 0,
967 SLAB_HWCACHE_ALIGN, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 if (cifs_mid_cachep == NULL)
969 return -ENOMEM;
970
Matthew Dobson93d23412006-03-26 01:37:50 -0800971 /* 3 is a reasonable minimum number of simultaneous operations */
972 cifs_mid_poolp = mempool_create_slab_pool(3, cifs_mid_cachep);
Steve French4523cc32007-04-30 20:13:06 +0000973 if (cifs_mid_poolp == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 kmem_cache_destroy(cifs_mid_cachep);
975 return -ENOMEM;
976 }
977
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 return 0;
979}
980
981static void
982cifs_destroy_mids(void)
983{
984 mempool_destroy(cifs_mid_poolp);
Alexey Dobriyan1a1d92c2006-09-27 01:49:40 -0700985 kmem_cache_destroy(cifs_mid_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986}
987
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988static int __init
989init_cifs(void)
990{
991 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 cifs_proc_init();
Jeff Laytone7ddee92008-11-14 13:44:38 -0500993 INIT_LIST_HEAD(&cifs_tcp_ses_list);
Steve French0eff0e22011-02-24 05:39:23 +0000994#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */
Steve French4ca9c192005-10-10 19:52:13 -0700995 INIT_LIST_HEAD(&GlobalDnotifyReqList);
996 INIT_LIST_HEAD(&GlobalDnotifyRsp_Q);
Steve French0eff0e22011-02-24 05:39:23 +0000997#endif /* was needed for dnotify, and will be needed for inotify when VFS fix */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998/*
999 * Initialize Global counters
1000 */
1001 atomic_set(&sesInfoAllocCount, 0);
1002 atomic_set(&tconInfoAllocCount, 0);
Steve French6dc0f872007-07-06 23:13:06 +00001003 atomic_set(&tcpSesAllocCount, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 atomic_set(&tcpSesReconnectCount, 0);
1005 atomic_set(&tconInfoReconnectCount, 0);
1006
1007 atomic_set(&bufAllocCount, 0);
Steve French4498eed52005-12-03 13:58:57 -08001008 atomic_set(&smBufAllocCount, 0);
1009#ifdef CONFIG_CIFS_STATS2
1010 atomic_set(&totBufAllocCount, 0);
1011 atomic_set(&totSmBufAllocCount, 0);
1012#endif /* CONFIG_CIFS_STATS2 */
1013
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 atomic_set(&midCount, 0);
1015 GlobalCurrentXid = 0;
1016 GlobalTotalActiveXid = 0;
1017 GlobalMaxActiveXid = 0;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05301018 spin_lock_init(&cifs_tcp_ses_lock);
Jeff Layton44772882010-10-15 15:34:03 -04001019 spin_lock_init(&cifs_file_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 spin_lock_init(&GlobalMid_Lock);
1021
Steve French4523cc32007-04-30 20:13:06 +00001022 if (cifs_max_pending < 2) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 cifs_max_pending = 2;
Joe Perchesb6b38f72010-04-21 03:50:45 +00001024 cFYI(1, "cifs_max_pending set to min of 2");
Steve French4523cc32007-04-30 20:13:06 +00001025 } else if (cifs_max_pending > 256) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 cifs_max_pending = 256;
Joe Perchesb6b38f72010-04-21 03:50:45 +00001027 cFYI(1, "cifs_max_pending set to max of 256");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 }
1029
Suresh Jayaramanf579cf32010-07-05 18:11:50 +05301030 rc = cifs_fscache_register();
1031 if (rc)
Steve Frenchd3bf5222010-09-22 19:15:36 +00001032 goto out_clean_proc;
Suresh Jayaramanf579cf32010-07-05 18:11:50 +05301033
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 rc = cifs_init_inodecache();
Steve French45af7a02006-04-21 22:52:25 +00001035 if (rc)
Steve Frenchd3bf5222010-09-22 19:15:36 +00001036 goto out_unreg_fscache;
Steve French45af7a02006-04-21 22:52:25 +00001037
1038 rc = cifs_init_mids();
1039 if (rc)
1040 goto out_destroy_inodecache;
1041
1042 rc = cifs_init_request_bufs();
1043 if (rc)
1044 goto out_destroy_mids;
1045
Jeff Layton84a15b92007-11-03 05:02:24 +00001046#ifdef CONFIG_CIFS_UPCALL
1047 rc = register_key_type(&cifs_spnego_key_type);
1048 if (rc)
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -05001049 goto out_destroy_request_bufs;
1050#endif /* CONFIG_CIFS_UPCALL */
1051
1052#ifdef CONFIG_CIFS_ACL
1053 rc = init_cifs_idmap();
1054 if (rc)
1055 goto out_destroy_request_bufs;
1056#endif /* CONFIG_CIFS_ACL */
1057
1058 rc = register_filesystem(&cifs_fs_type);
1059 if (rc)
1060 goto out_destroy_request_bufs;
Steve French45af7a02006-04-21 22:52:25 +00001061
Steve French45af7a02006-04-21 22:52:25 +00001062 return 0;
1063
Steve Frenchd3bf5222010-09-22 19:15:36 +00001064out_destroy_request_bufs:
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -05001065#ifdef CONFIG_CIFS_ACL
1066 exit_cifs_idmap();
1067#endif
1068#ifdef CONFIG_CIFS_UPCALL
1069 unregister_key_type(&cifs_spnego_key_type);
1070#endif
Steve French45af7a02006-04-21 22:52:25 +00001071 cifs_destroy_request_bufs();
Steve Frenchd3bf5222010-09-22 19:15:36 +00001072out_destroy_mids:
Steve French45af7a02006-04-21 22:52:25 +00001073 cifs_destroy_mids();
Steve Frenchd3bf5222010-09-22 19:15:36 +00001074out_destroy_inodecache:
Steve French45af7a02006-04-21 22:52:25 +00001075 cifs_destroy_inodecache();
Steve Frenchd3bf5222010-09-22 19:15:36 +00001076out_unreg_fscache:
Suresh Jayaramanf579cf32010-07-05 18:11:50 +05301077 cifs_fscache_unregister();
Steve Frenchd3bf5222010-09-22 19:15:36 +00001078out_clean_proc:
1079 cifs_proc_clean();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 return rc;
1081}
1082
1083static void __exit
1084exit_cifs(void)
1085{
Joe Perchesb6b38f72010-04-21 03:50:45 +00001086 cFYI(DBG2, "exit_cifs");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 cifs_proc_clean();
Suresh Jayaramanf579cf32010-07-05 18:11:50 +05301088 cifs_fscache_unregister();
Steve French61033352008-01-09 16:21:36 +00001089#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov78d31a32008-04-24 12:56:07 +04001090 cifs_dfs_release_automount_timer();
Steve French61033352008-01-09 16:21:36 +00001091#endif
Shirish Pargaonkar4d79dba2011-04-27 23:34:35 -05001092#ifdef CONFIG_CIFS_ACL
1093 cifs_destroy_idmaptrees();
1094 exit_cifs_idmap();
1095#endif
Jeff Layton84a15b92007-11-03 05:02:24 +00001096#ifdef CONFIG_CIFS_UPCALL
1097 unregister_key_type(&cifs_spnego_key_type);
1098#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 unregister_filesystem(&cifs_fs_type);
1100 cifs_destroy_inodecache();
1101 cifs_destroy_mids();
1102 cifs_destroy_request_bufs();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103}
1104
1105MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
Steve French6dc0f872007-07-06 23:13:06 +00001106MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107MODULE_DESCRIPTION
Steve French63135e02007-07-17 17:34:02 +00001108 ("VFS to access servers complying with the SNIA CIFS Specification "
1109 "e.g. Samba and Windows");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110MODULE_VERSION(CIFS_VERSION);
1111module_init(init_cifs)
1112module_exit(exit_cifs)