blob: ad235d604a0b8f123b869bc5c80df55d5b5642fc [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>
Alessio Igor Bogani67e55202009-04-24 09:06:53 +020038#include <linux/smp_lock.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>
Steve French61033352008-01-09 16:21:36 +000048#include "dns_resolve.h"
Jeff Laytone5459372007-11-03 05:11:06 +000049#include "cifs_spnego.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
51
52#ifdef CONFIG_CIFS_QUOTA
Alexey Dobriyan0d54b212009-09-21 17:01:09 -070053static const struct quotactl_ops cifs_quotactl_ops;
Steve French35c11fd2007-02-27 05:09:35 +000054#endif /* QUOTA */
55
Linus Torvalds1da177e2005-04-16 15:20:36 -070056int cifsFYI = 0;
57int cifsERROR = 1;
58int traceSMB = 0;
59unsigned int oplockEnabled = 1;
60unsigned int experimEnabled = 0;
61unsigned int linuxExtEnabled = 1;
62unsigned int lookupCacheEnabled = 1;
63unsigned int multiuser_mount = 0;
Steve French39798772006-05-31 22:40:51 +000064unsigned int extended_security = CIFSSEC_DEF;
65/* unsigned int ntlmv2_support = 0; */
Linus Torvalds1da177e2005-04-16 15:20:36 -070066unsigned int sign_CIFS_PDUs = 1;
Josef 'Jeff' Sipekee9b6d62007-02-12 00:55:41 -080067static const struct super_operations cifs_super_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -070068unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
69module_param(CIFSMaxBufSize, int, 0);
Steve French63135e02007-07-17 17:34:02 +000070MODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header). "
71 "Default: 16384 Range: 8192 to 130048");
Linus Torvalds1da177e2005-04-16 15:20:36 -070072unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
73module_param(cifs_min_rcv, int, 0);
Steve French63135e02007-07-17 17:34:02 +000074MODULE_PARM_DESC(cifs_min_rcv, "Network buffers in pool. Default: 4 Range: "
75 "1 to 64");
Linus Torvalds1da177e2005-04-16 15:20:36 -070076unsigned int cifs_min_small = 30;
77module_param(cifs_min_small, int, 0);
Steve French63135e02007-07-17 17:34:02 +000078MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 "
79 "Range: 2 to 256");
Linus Torvalds1da177e2005-04-16 15:20:36 -070080unsigned int cifs_max_pending = CIFS_MAX_REQ;
81module_param(cifs_max_pending, int, 0);
Steve French63135e02007-07-17 17:34:02 +000082MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. "
83 "Default: 50 Range: 2 to 256");
Linus Torvalds1da177e2005-04-16 15:20:36 -070084
Linus Torvalds1da177e2005-04-16 15:20:36 -070085extern mempool_t *cifs_sm_req_poolp;
86extern mempool_t *cifs_req_poolp;
87extern mempool_t *cifs_mid_poolp;
88
Christoph Lametere18b8902006-12-06 20:33:20 -080089extern struct kmem_cache *cifs_oplock_cachep;
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
91static int
92cifs_read_super(struct super_block *sb, void *data,
93 const char *devname, int silent)
94{
95 struct inode *inode;
96 struct cifs_sb_info *cifs_sb;
97 int rc = 0;
Steve French50c2f752007-07-13 00:33:32 +000098
Steve French1b2b2122007-02-17 04:30:54 +000099 /* BB should we make this contingent on mount parm? */
100 sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
Steve French790fe572007-07-07 19:25:05 +0000101 sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102 cifs_sb = CIFS_SB(sb);
Steve French4523cc32007-04-30 20:13:06 +0000103 if (cifs_sb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
Jens Axboe8044f7f2010-04-22 12:09:48 +0200106 rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
107 if (rc) {
108 kfree(cifs_sb);
109 return rc;
110 }
111
Igor Mammedove6ab1582008-01-11 01:49:48 +0000112#ifdef CONFIG_CIFS_DFS_UPCALL
113 /* copy mount params to sb for use in submounts */
114 /* BB: should we move this after the mount so we
115 * do not have to do the copy on failed mounts?
116 * BB: May be it is better to do simple copy before
117 * complex operation (mount), and in case of fail
118 * just exit instead of doing mount and attempting
119 * undo it if this copy fails?*/
Steve French79ee9a82008-06-10 21:37:02 +0000120 if (data) {
121 int len = strlen(data);
122 cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL);
123 if (cifs_sb->mountdata == NULL) {
Jens Axboe8044f7f2010-04-22 12:09:48 +0200124 bdi_destroy(&cifs_sb->bdi);
Steve French79ee9a82008-06-10 21:37:02 +0000125 kfree(sb->s_fs_info);
126 sb->s_fs_info = NULL;
127 return -ENOMEM;
128 }
129 strncpy(cifs_sb->mountdata, data, len + 1);
130 cifs_sb->mountdata[len] = '\0';
Igor Mammedove6ab1582008-01-11 01:49:48 +0000131 }
Igor Mammedove6ab1582008-01-11 01:49:48 +0000132#endif
133
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 rc = cifs_mount(sb, cifs_sb, data, devname);
135
136 if (rc) {
137 if (!silent)
138 cERROR(1,
139 ("cifs_mount failed w/return code = %d", rc));
140 goto out_mount_failed;
141 }
142
143 sb->s_magic = CIFS_MAGIC_NUMBER;
144 sb->s_op = &cifs_super_ops;
Jens Axboe8044f7f2010-04-22 12:09:48 +0200145 sb->s_bdi = &cifs_sb->bdi;
Steve French4523cc32007-04-30 20:13:06 +0000146/* if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
Steve French790fe572007-07-07 19:25:05 +0000147 sb->s_blocksize =
148 cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149#ifdef CONFIG_CIFS_QUOTA
150 sb->s_qcop = &cifs_quotactl_ops;
151#endif
152 sb->s_blocksize = CIFS_MAX_MSGSIZE;
153 sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
Jeff Laytonbd433d42009-05-27 09:37:34 -0400154 inode = cifs_root_iget(sb, ROOT_I);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155
David Howellsce634ab2008-02-07 00:15:33 -0800156 if (IS_ERR(inode)) {
157 rc = PTR_ERR(inode);
158 inode = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 goto out_no_root;
160 }
161
162 sb->s_root = d_alloc_root(inode);
163
164 if (!sb->s_root) {
165 rc = -ENOMEM;
166 goto out_no_root;
167 }
Steve French50c2f752007-07-13 00:33:32 +0000168
Steve French7521a3c2007-07-11 18:30:34 +0000169#ifdef CONFIG_CIFS_EXPERIMENTAL
170 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
171 cFYI(1, ("export ops supported"));
172 sb->s_export_op = &cifs_export_ops;
173 }
174#endif /* EXPERIMENTAL */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175
176 return 0;
177
178out_no_root:
179 cERROR(1, ("cifs_read_super: get root inode failed"));
180 if (inode)
181 iput(inode);
Steve French54b46022008-08-11 22:31:40 +0000182
Steve French2c731af2008-08-11 22:28:53 +0000183 cifs_umount(sb, cifs_sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184
185out_mount_failed:
Steve French4523cc32007-04-30 20:13:06 +0000186 if (cifs_sb) {
Igor Mammedove6ab1582008-01-11 01:49:48 +0000187#ifdef CONFIG_CIFS_DFS_UPCALL
188 if (cifs_sb->mountdata) {
189 kfree(cifs_sb->mountdata);
190 cifs_sb->mountdata = NULL;
191 }
192#endif
Thomas Gleixner6d729e42009-08-16 21:05:08 +0000193 unload_nls(cifs_sb->local_nls);
Jens Axboe8044f7f2010-04-22 12:09:48 +0200194 bdi_destroy(&cifs_sb->bdi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 kfree(cifs_sb);
196 }
197 return rc;
198}
199
200static void
201cifs_put_super(struct super_block *sb)
202{
203 int rc = 0;
204 struct cifs_sb_info *cifs_sb;
205
206 cFYI(1, ("In cifs_put_super"));
207 cifs_sb = CIFS_SB(sb);
Steve French4523cc32007-04-30 20:13:06 +0000208 if (cifs_sb == NULL) {
Steve French790fe572007-07-07 19:25:05 +0000209 cFYI(1, ("Empty cifs superblock info passed to unmount"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 return;
211 }
Christoph Hellwig6cfd0142009-05-05 15:40:36 +0200212
213 lock_kernel();
214
Steve French790fe572007-07-07 19:25:05 +0000215 rc = cifs_umount(sb, cifs_sb);
Steve Frenchad7a2922008-02-07 23:25:02 +0000216 if (rc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 cERROR(1, ("cifs_umount failed with return code %d", rc));
Igor Mammedove6ab1582008-01-11 01:49:48 +0000218#ifdef CONFIG_CIFS_DFS_UPCALL
219 if (cifs_sb->mountdata) {
220 kfree(cifs_sb->mountdata);
221 cifs_sb->mountdata = NULL;
222 }
223#endif
224
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 unload_nls(cifs_sb->local_nls);
Jens Axboe8044f7f2010-04-22 12:09:48 +0200226 bdi_destroy(&cifs_sb->bdi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 kfree(cifs_sb);
Christoph Hellwig6cfd0142009-05-05 15:40:36 +0200228
229 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230}
231
232static int
David Howells726c3342006-06-23 02:02:58 -0700233cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234{
David Howells726c3342006-06-23 02:02:58 -0700235 struct super_block *sb = dentry->d_sb;
Steve French39da9842008-04-28 04:04:34 +0000236 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
237 struct cifsTconInfo *tcon = cifs_sb->tcon;
Steve Frenchc81156d2005-04-28 22:41:07 -0700238 int rc = -EOPNOTSUPP;
Steve French39da9842008-04-28 04:04:34 +0000239 int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240
241 xid = GetXid();
242
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 buf->f_type = CIFS_MAGIC_NUMBER;
244
Steve French39da9842008-04-28 04:04:34 +0000245 /*
246 * PATH_MAX may be too long - it would presumably be total path,
247 * but note that some servers (includinng Samba 3) have a shorter
248 * maximum path.
249 *
250 * Instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO.
251 */
252 buf->f_namelen = PATH_MAX;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 buf->f_files = 0; /* undefined */
254 buf->f_ffree = 0; /* unlimited */
255
Steve French39da9842008-04-28 04:04:34 +0000256 /*
257 * We could add a second check for a QFS Unix capability bit
258 */
259 if ((tcon->ses->capabilities & CAP_UNIX) &&
260 (CIFS_POSIX_EXTENSIONS & le64_to_cpu(tcon->fsUnixInfo.Capability)))
261 rc = CIFSSMBQFSPosixInfo(xid, tcon, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
Steve French39da9842008-04-28 04:04:34 +0000263 /*
264 * Only need to call the old QFSInfo if failed on newer one,
265 * e.g. by OS/2.
266 **/
267 if (rc && (tcon->ses->capabilities & CAP_NT_SMBS))
268 rc = CIFSSMBQFSInfo(xid, tcon, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269
Steve French39da9842008-04-28 04:04:34 +0000270 /*
271 * Some old Windows servers also do not support level 103, retry with
272 * older level one if old server failed the previous call or we
273 * bypassed it because we detected that this was an older LANMAN sess
274 */
Steve French4523cc32007-04-30 20:13:06 +0000275 if (rc)
Steve French39da9842008-04-28 04:04:34 +0000276 rc = SMBOldQFSInfo(xid, tcon, buf);
277
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 FreeXid(xid);
Steve French39da9842008-04-28 04:04:34 +0000279 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280}
281
Al Viroe6305c42008-07-15 21:03:57 -0400282static int cifs_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283{
284 struct cifs_sb_info *cifs_sb;
285
286 cifs_sb = CIFS_SB(inode->i_sb);
287
Miklos Szeredif696a362008-07-31 13:41:58 +0200288 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
289 if ((mask & MAY_EXEC) && !execute_ok(inode))
290 return -EACCES;
291 else
292 return 0;
293 } else /* file mode might have been restricted at mount time
Steve French50c2f752007-07-13 00:33:32 +0000294 on the client (above and beyond ACL on servers) for
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 servers which do not support setting and viewing mode bits,
Steve French50c2f752007-07-13 00:33:32 +0000296 so allowing client to check permissions is useful */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 return generic_permission(inode, mask, NULL);
298}
299
Christoph Lametere18b8902006-12-06 20:33:20 -0800300static struct kmem_cache *cifs_inode_cachep;
301static struct kmem_cache *cifs_req_cachep;
302static struct kmem_cache *cifs_mid_cachep;
303struct kmem_cache *cifs_oplock_cachep;
304static struct kmem_cache *cifs_sm_req_cachep;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305mempool_t *cifs_sm_req_poolp;
306mempool_t *cifs_req_poolp;
307mempool_t *cifs_mid_poolp;
308
309static struct inode *
310cifs_alloc_inode(struct super_block *sb)
311{
312 struct cifsInodeInfo *cifs_inode;
Christoph Lametere94b1762006-12-06 20:33:17 -0800313 cifs_inode = kmem_cache_alloc(cifs_inode_cachep, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 if (!cifs_inode)
315 return NULL;
316 cifs_inode->cifsAttrs = 0x20; /* default */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 cifs_inode->time = 0;
Jeff Laytoncea21802007-11-20 23:19:03 +0000318 cifs_inode->write_behind_rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 /* Until the file is open and we have gotten oplock
320 info back from the server, can not assume caching of
321 file data or metadata */
Steve French4b18f2a2008-04-29 00:06:05 +0000322 cifs_inode->clientCanCacheRead = false;
323 cifs_inode->clientCanCacheAll = false;
Jeff Layton9a8165f2008-10-17 21:03:20 -0400324 cifs_inode->delete_pending = false;
Jeff Laytondf2cf172010-02-12 07:44:16 -0500325 cifs_inode->invalid_mapping = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
Jeff Laytonfbec9ab2009-04-03 13:44:00 -0400327 cifs_inode->server_eof = 0;
Steve French50c2f752007-07-13 00:33:32 +0000328
Steve French1b2b2122007-02-17 04:30:54 +0000329 /* Can not set i_flags here - they get immediately overwritten
330 to zero by the VFS */
331/* cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 INIT_LIST_HEAD(&cifs_inode->openFileList);
333 return &cifs_inode->vfs_inode;
334}
335
336static void
337cifs_destroy_inode(struct inode *inode)
338{
339 kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
340}
341
Jeff Layton61f98ff2009-06-11 10:27:32 -0400342static void
343cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
344{
345 seq_printf(s, ",addr=");
346
347 switch (server->addr.sockAddr.sin_family) {
348 case AF_INET:
349 seq_printf(s, "%pI4", &server->addr.sockAddr.sin_addr.s_addr);
350 break;
351 case AF_INET6:
352 seq_printf(s, "%pI6",
353 &server->addr.sockAddr6.sin6_addr.s6_addr);
354 if (server->addr.sockAddr6.sin6_scope_id)
355 seq_printf(s, "%%%u",
356 server->addr.sockAddr6.sin6_scope_id);
357 break;
358 default:
359 seq_printf(s, "(unknown)");
360 }
361}
362
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363/*
364 * cifs_show_options() is for displaying mount options in /proc/mounts.
365 * Not all settable options are displayed but most of the important
366 * ones are.
367 */
368static int
369cifs_show_options(struct seq_file *s, struct vfsmount *m)
370{
Jeff Layton8e047d02009-08-28 10:11:10 -0400371 struct cifs_sb_info *cifs_sb = CIFS_SB(m->mnt_sb);
372 struct cifsTconInfo *tcon = cifs_sb->tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
Jeff Layton8e047d02009-08-28 10:11:10 -0400374 seq_printf(s, ",unc=%s", tcon->treeName);
Jeff Layton8616e0f2009-06-11 10:27:28 -0400375 if (tcon->ses->userName)
376 seq_printf(s, ",username=%s", tcon->ses->userName);
377 if (tcon->ses->domainName)
378 seq_printf(s, ",domain=%s", tcon->ses->domainName);
379
Jeff Layton8616e0f2009-06-11 10:27:28 -0400380 seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
Jeff Layton340481a32009-06-11 10:27:29 -0400381 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
382 seq_printf(s, ",forceuid");
Jeff Layton4486d6e2009-08-03 12:45:10 -0400383 else
384 seq_printf(s, ",noforceuid");
Jeff Layton340481a32009-06-11 10:27:29 -0400385
Jeff Layton8616e0f2009-06-11 10:27:28 -0400386 seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
Jeff Layton340481a32009-06-11 10:27:29 -0400387 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
388 seq_printf(s, ",forcegid");
Jeff Layton4486d6e2009-08-03 12:45:10 -0400389 else
390 seq_printf(s, ",noforcegid");
Jeff Layton8616e0f2009-06-11 10:27:28 -0400391
Jeff Layton61f98ff2009-06-11 10:27:32 -0400392 cifs_show_address(s, tcon->ses->server);
Jeff Layton8616e0f2009-06-11 10:27:28 -0400393
394 if (!tcon->unix_ext)
395 seq_printf(s, ",file_mode=0%o,dir_mode=0%o",
Steve French2b280fa2008-05-17 03:12:45 +0000396 cifs_sb->mnt_file_mode,
397 cifs_sb->mnt_dir_mode);
Jeff Layton8616e0f2009-06-11 10:27:28 -0400398 if (tcon->seal)
399 seq_printf(s, ",seal");
400 if (tcon->nocase)
401 seq_printf(s, ",nocase");
402 if (tcon->retry)
403 seq_printf(s, ",hard");
404 if (cifs_sb->prepath)
405 seq_printf(s, ",prepath=%s", cifs_sb->prepath);
406 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
407 seq_printf(s, ",posixpaths");
408 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
409 seq_printf(s, ",setuids");
410 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
411 seq_printf(s, ",serverino");
412 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
413 seq_printf(s, ",directio");
414 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
415 seq_printf(s, ",nouser_xattr");
416 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
417 seq_printf(s, ",mapchars");
418 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
419 seq_printf(s, ",sfu");
420 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
421 seq_printf(s, ",nobrl");
422 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
423 seq_printf(s, ",cifsacl");
424 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
425 seq_printf(s, ",dynperm");
426 if (m->mnt_sb->s_flags & MS_POSIXACL)
427 seq_printf(s, ",acl");
Steve French2b280fa2008-05-17 03:12:45 +0000428
Jeff Layton8616e0f2009-06-11 10:27:28 -0400429 seq_printf(s, ",rsize=%d", cifs_sb->rsize);
430 seq_printf(s, ",wsize=%d", cifs_sb->wsize);
431
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 return 0;
433}
434
435#ifdef CONFIG_CIFS_QUOTA
Steve French50c2f752007-07-13 00:33:32 +0000436int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid,
437 struct fs_disk_quota *pdquota)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438{
439 int xid;
440 int rc = 0;
441 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
442 struct cifsTconInfo *pTcon;
Steve French50c2f752007-07-13 00:33:32 +0000443
Steve French4523cc32007-04-30 20:13:06 +0000444 if (cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 pTcon = cifs_sb->tcon;
446 else
447 return -EIO;
448
449
450 xid = GetXid();
Steve French4523cc32007-04-30 20:13:06 +0000451 if (pTcon) {
Steve French50c2f752007-07-13 00:33:32 +0000452 cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
Steve French61e74802008-12-03 00:57:54 +0000453 } else
Cyrill Gorcunov95ba7362007-08-24 00:23:36 +0000454 rc = -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455
456 FreeXid(xid);
457 return rc;
458}
459
Steve French50c2f752007-07-13 00:33:32 +0000460int cifs_xquota_get(struct super_block *sb, int quota_type, qid_t qid,
461 struct fs_disk_quota *pdquota)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462{
463 int xid;
464 int rc = 0;
465 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
466 struct cifsTconInfo *pTcon;
467
Steve French4523cc32007-04-30 20:13:06 +0000468 if (cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 pTcon = cifs_sb->tcon;
470 else
471 return -EIO;
472
473 xid = GetXid();
Steve French4523cc32007-04-30 20:13:06 +0000474 if (pTcon) {
Steve French50c2f752007-07-13 00:33:32 +0000475 cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
Steve French61e74802008-12-03 00:57:54 +0000476 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 rc = -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
479 FreeXid(xid);
480 return rc;
481}
482
Steve French50c2f752007-07-13 00:33:32 +0000483int cifs_xstate_set(struct super_block *sb, unsigned int flags, int operation)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484{
Steve French50c2f752007-07-13 00:33:32 +0000485 int xid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 int rc = 0;
487 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
488 struct cifsTconInfo *pTcon;
489
Steve French4523cc32007-04-30 20:13:06 +0000490 if (cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 pTcon = cifs_sb->tcon;
492 else
493 return -EIO;
494
495 xid = GetXid();
Steve French4523cc32007-04-30 20:13:06 +0000496 if (pTcon) {
Steve French50c2f752007-07-13 00:33:32 +0000497 cFYI(1, ("flags: 0x%x operation: 0x%x", flags, operation));
Steve French61e74802008-12-03 00:57:54 +0000498 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 rc = -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500
501 FreeXid(xid);
502 return rc;
503}
504
Steve French50c2f752007-07-13 00:33:32 +0000505int cifs_xstate_get(struct super_block *sb, struct fs_quota_stat *qstats)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506{
507 int xid;
508 int rc = 0;
509 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
510 struct cifsTconInfo *pTcon;
511
Steve French61e74802008-12-03 00:57:54 +0000512 if (cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 pTcon = cifs_sb->tcon;
Steve French61e74802008-12-03 00:57:54 +0000514 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 return -EIO;
Steve French61e74802008-12-03 00:57:54 +0000516
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 xid = GetXid();
Steve French4523cc32007-04-30 20:13:06 +0000518 if (pTcon) {
Steve French50c2f752007-07-13 00:33:32 +0000519 cFYI(1, ("pqstats %p", qstats));
Steve French61e74802008-12-03 00:57:54 +0000520 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 rc = -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522
523 FreeXid(xid);
524 return rc;
525}
526
Alexey Dobriyan0d54b212009-09-21 17:01:09 -0700527static const struct quotactl_ops cifs_quotactl_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 .set_xquota = cifs_xquota_set,
Roel Kluin6f7e8f32008-02-12 20:38:10 +0000529 .get_xquota = cifs_xquota_get,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 .set_xstate = cifs_xstate_set,
531 .get_xstate = cifs_xstate_get,
532};
533#endif
534
Al Viro42faad92008-04-24 07:21:56 -0400535static void cifs_umount_begin(struct super_block *sb)
Steve French68058e72005-10-10 10:34:22 -0700536{
Al Viro42faad92008-04-24 07:21:56 -0400537 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
Steve French50c2f752007-07-13 00:33:32 +0000538 struct cifsTconInfo *tcon;
Steve French68058e72005-10-10 10:34:22 -0700539
Steve French4523cc32007-04-30 20:13:06 +0000540 if (cifs_sb == NULL)
Steve French9e2e85f2005-10-10 14:28:38 -0700541 return;
542
543 tcon = cifs_sb->tcon;
Steve French4523cc32007-04-30 20:13:06 +0000544 if (tcon == NULL)
Steve French9e2e85f2005-10-10 14:28:38 -0700545 return;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500546
547 read_lock(&cifs_tcp_ses_lock);
Steve Frenchad8034f2009-06-26 03:25:49 +0000548 if ((tcon->tc_count > 1) || (tcon->tidStatus == CifsExiting)) {
549 /* we have other mounts to same share or we have
550 already tried to force umount this and woken up
551 all waiting network requests, nothing to do */
552 read_unlock(&cifs_tcp_ses_lock);
553 return;
554 } else if (tcon->tc_count == 1)
Steve French5e1253b2005-10-10 14:06:37 -0700555 tcon->tidStatus = CifsExiting;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500556 read_unlock(&cifs_tcp_ses_lock);
Steve French5e1253b2005-10-10 14:06:37 -0700557
Steve French3a5ff612006-07-14 22:37:11 +0000558 /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
Steve French7b7abfe2005-11-09 15:21:09 -0800559 /* cancel_notify_requests(tcon); */
Steve French50c2f752007-07-13 00:33:32 +0000560 if (tcon->ses && tcon->ses->server) {
561 cFYI(1, ("wake up tasks now - umount begin not complete"));
Steve French9e2e85f2005-10-10 14:28:38 -0700562 wake_up_all(&tcon->ses->server->request_q);
Steve French6ab16d22005-11-29 20:55:11 -0800563 wake_up_all(&tcon->ses->server->response_q);
564 msleep(1); /* yield */
565 /* we have to kick the requests once more */
566 wake_up_all(&tcon->ses->server->response_q);
567 msleep(1);
Steve French5e1253b2005-10-10 14:06:37 -0700568 }
Steve French68058e72005-10-10 10:34:22 -0700569
570 return;
571}
Steve French68058e72005-10-10 10:34:22 -0700572
Steve Frenchbf97d282006-09-28 21:34:06 +0000573#ifdef CONFIG_CIFS_STATS2
574static int cifs_show_stats(struct seq_file *s, struct vfsmount *mnt)
575{
576 /* BB FIXME */
577 return 0;
578}
579#endif
580
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581static int cifs_remount(struct super_block *sb, int *flags, char *data)
582{
583 *flags |= MS_NODIRATIME;
584 return 0;
585}
586
Josef 'Jeff' Sipekee9b6d62007-02-12 00:55:41 -0800587static const struct super_operations cifs_super_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 .put_super = cifs_put_super,
589 .statfs = cifs_statfs,
590 .alloc_inode = cifs_alloc_inode,
591 .destroy_inode = cifs_destroy_inode,
Steve French50c2f752007-07-13 00:33:32 +0000592/* .drop_inode = generic_delete_inode,
593 .delete_inode = cifs_delete_inode, */ /* Do not need above two
594 functions unless later we add lazy close of inodes or unless the
595 kernel forgets to call us with the same number of releases (closes)
596 as opens */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 .show_options = cifs_show_options,
Steve French7b7abfe2005-11-09 15:21:09 -0800598 .umount_begin = cifs_umount_begin,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 .remount_fs = cifs_remount,
Steve Frenchbf97d282006-09-28 21:34:06 +0000600#ifdef CONFIG_CIFS_STATS2
Steve Frenchf46d3e12006-09-30 01:08:55 +0000601 .show_stats = cifs_show_stats,
Steve Frenchbf97d282006-09-28 21:34:06 +0000602#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603};
604
David Howells454e2392006-06-23 02:02:57 -0700605static int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606cifs_get_sb(struct file_system_type *fs_type,
David Howells454e2392006-06-23 02:02:57 -0700607 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608{
609 int rc;
610 struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
611
612 cFYI(1, ("Devname: %s flags: %d ", dev_name, flags));
613
614 if (IS_ERR(sb))
David Howells454e2392006-06-23 02:02:57 -0700615 return PTR_ERR(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616
617 sb->s_flags = flags;
618
Theodore Ts'o9b04c992006-03-24 03:15:10 -0800619 rc = cifs_read_super(sb, data, dev_name, flags & MS_SILENT ? 1 : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 if (rc) {
Al Viro6f5bbff2009-05-06 01:34:22 -0400621 deactivate_locked_super(sb);
David Howells454e2392006-06-23 02:02:57 -0700622 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 }
624 sb->s_flags |= MS_ACTIVE;
Sukadev Bhattiprolua3ec9472009-03-04 12:06:34 -0800625 simple_set_mnt(mnt, sb);
626 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627}
628
Badari Pulavarty027445c2006-09-30 23:28:46 -0700629static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
630 unsigned long nr_segs, loff_t pos)
Steve French87c89dd2005-11-17 17:03:00 -0800631{
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -0800632 struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
Steve French87c89dd2005-11-17 17:03:00 -0800633 ssize_t written;
634
Badari Pulavarty027445c2006-09-30 23:28:46 -0700635 written = generic_file_aio_write(iocb, iov, nr_segs, pos);
Steve French87c89dd2005-11-17 17:03:00 -0800636 if (!CIFS_I(inode)->clientCanCacheAll)
637 filemap_fdatawrite(inode->i_mapping);
638 return written;
639}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
Steve Frenchc32a0b62006-01-12 14:41:28 -0800641static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
642{
643 /* origin == SEEK_END => we must revalidate the cached file length */
Steve French0889a942006-09-23 22:11:07 +0000644 if (origin == SEEK_END) {
Steve French030e9d82007-02-01 04:27:59 +0000645 int retval;
646
647 /* some applications poll for the file length in this strange
648 way so we must seek to end on non-oplocked files by
649 setting the revalidate time to zero */
Christoph Hellwigc33f8d32007-04-02 18:47:20 +0000650 CIFS_I(file->f_path.dentry->d_inode)->time = 0;
Steve French030e9d82007-02-01 04:27:59 +0000651
Jeff Laytonabab0952010-02-12 07:44:18 -0500652 retval = cifs_revalidate_file(file);
Steve Frenchc32a0b62006-01-12 14:41:28 -0800653 if (retval < 0)
654 return (loff_t)retval;
655 }
Andi Kleen9465efc2008-06-27 11:05:24 +0200656 return generic_file_llseek_unlocked(file, offset, origin);
Steve Frenchc32a0b62006-01-12 14:41:28 -0800657}
658
Steve French84210e92008-10-23 04:42:37 +0000659#ifdef CONFIG_CIFS_EXPERIMENTAL
660static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
661{
662 /* note that this is called by vfs setlease with the BKL held
663 although I doubt that BKL is needed here in cifs */
664 struct inode *inode = file->f_path.dentry->d_inode;
665
666 if (!(S_ISREG(inode->i_mode)))
667 return -EINVAL;
668
669 /* check if file is oplocked */
670 if (((arg == F_RDLCK) &&
671 (CIFS_I(inode)->clientCanCacheRead)) ||
672 ((arg == F_WRLCK) &&
673 (CIFS_I(inode)->clientCanCacheAll)))
674 return generic_setlease(file, arg, lease);
675 else if (CIFS_SB(inode->i_sb)->tcon->local_lease &&
676 !CIFS_I(inode)->clientCanCacheRead)
677 /* If the server claims to support oplock on this
678 file, then we still need to check oplock even
679 if the local_lease mount option is set, but there
680 are servers which do not support oplock for which
681 this mount option may be useful if the user
682 knows that the file won't be changed on the server
683 by anyone else */
684 return generic_setlease(file, arg, lease);
685 else
686 return -EAGAIN;
687}
688#endif
689
Igor Mammedove6ab1582008-01-11 01:49:48 +0000690struct file_system_type cifs_fs_type = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 .owner = THIS_MODULE,
692 .name = "cifs",
693 .get_sb = cifs_get_sb,
694 .kill_sb = kill_anon_super,
695 /* .fs_flags */
696};
Arjan van de Ven754661f2007-02-12 00:55:38 -0800697const struct inode_operations cifs_dir_inode_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 .create = cifs_create,
699 .lookup = cifs_lookup,
700 .getattr = cifs_getattr,
701 .unlink = cifs_unlink,
702 .link = cifs_hardlink,
703 .mkdir = cifs_mkdir,
704 .rmdir = cifs_rmdir,
705 .rename = cifs_rename,
706 .permission = cifs_permission,
707/* revalidate:cifs_revalidate, */
708 .setattr = cifs_setattr,
709 .symlink = cifs_symlink,
710 .mknod = cifs_mknod,
711#ifdef CONFIG_CIFS_XATTR
712 .setxattr = cifs_setxattr,
713 .getxattr = cifs_getxattr,
714 .listxattr = cifs_listxattr,
715 .removexattr = cifs_removexattr,
716#endif
717};
718
Arjan van de Ven754661f2007-02-12 00:55:38 -0800719const struct inode_operations cifs_file_inode_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720/* revalidate:cifs_revalidate, */
721 .setattr = cifs_setattr,
722 .getattr = cifs_getattr, /* do we need this anymore? */
723 .rename = cifs_rename,
724 .permission = cifs_permission,
725#ifdef CONFIG_CIFS_XATTR
726 .setxattr = cifs_setxattr,
727 .getxattr = cifs_getxattr,
728 .listxattr = cifs_listxattr,
729 .removexattr = cifs_removexattr,
Steve French50c2f752007-07-13 00:33:32 +0000730#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731};
732
Arjan van de Ven754661f2007-02-12 00:55:38 -0800733const struct inode_operations cifs_symlink_inode_ops = {
Steve French50c2f752007-07-13 00:33:32 +0000734 .readlink = generic_readlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 .follow_link = cifs_follow_link,
736 .put_link = cifs_put_link,
737 .permission = cifs_permission,
738 /* BB add the following two eventually */
739 /* revalidate: cifs_revalidate,
740 setattr: cifs_notify_change, *//* BB do we need notify change */
741#ifdef CONFIG_CIFS_XATTR
742 .setxattr = cifs_setxattr,
743 .getxattr = cifs_getxattr,
744 .listxattr = cifs_listxattr,
745 .removexattr = cifs_removexattr,
Steve French50c2f752007-07-13 00:33:32 +0000746#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747};
748
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800749const struct file_operations cifs_file_ops = {
Steve French87c89dd2005-11-17 17:03:00 -0800750 .read = do_sync_read,
751 .write = do_sync_write,
Steve French87c89dd2005-11-17 17:03:00 -0800752 .aio_read = generic_file_aio_read,
753 .aio_write = cifs_file_aio_write,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 .open = cifs_open,
755 .release = cifs_close,
756 .lock = cifs_lock,
757 .fsync = cifs_fsync,
758 .flush = cifs_flush,
759 .mmap = cifs_file_mmap,
Jens Axboe5ffc4ef2007-06-01 11:49:19 +0200760 .splice_read = generic_file_splice_read,
Steve Frenchc32a0b62006-01-12 14:41:28 -0800761 .llseek = cifs_llseek,
Steve Frenchc67593a2005-04-28 22:41:04 -0700762#ifdef CONFIG_CIFS_POSIX
Steve Frenchf9ddcca2008-05-15 05:51:55 +0000763 .unlocked_ioctl = cifs_ioctl,
Steve Frenchc67593a2005-04-28 22:41:04 -0700764#endif /* CONFIG_CIFS_POSIX */
765
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766#ifdef CONFIG_CIFS_EXPERIMENTAL
Steve French84210e92008-10-23 04:42:37 +0000767 .setlease = cifs_setlease,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768#endif /* CONFIG_CIFS_EXPERIMENTAL */
769};
770
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800771const struct file_operations cifs_file_direct_ops = {
Steve Frencha994b8f2009-12-07 05:44:46 +0000772 /* no aio, no readv -
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 BB reevaluate whether they can be done with directio, no cache */
774 .read = cifs_user_read,
775 .write = cifs_user_write,
776 .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,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787#ifdef CONFIG_CIFS_EXPERIMENTAL
Steve French84210e92008-10-23 04:42:37 +0000788 .setlease = cifs_setlease,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789#endif /* CONFIG_CIFS_EXPERIMENTAL */
790};
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800791const struct file_operations cifs_file_nobrl_ops = {
Steve French87c89dd2005-11-17 17:03:00 -0800792 .read = do_sync_read,
793 .write = do_sync_write,
Steve French87c89dd2005-11-17 17:03:00 -0800794 .aio_read = generic_file_aio_read,
795 .aio_write = cifs_file_aio_write,
796 .open = cifs_open,
797 .release = cifs_close,
798 .fsync = cifs_fsync,
799 .flush = cifs_flush,
800 .mmap = cifs_file_mmap,
Jens Axboe5ffc4ef2007-06-01 11:49:19 +0200801 .splice_read = generic_file_splice_read,
Steve Frenchc32a0b62006-01-12 14:41:28 -0800802 .llseek = cifs_llseek,
Steve French8b94bcb2005-11-11 11:41:00 -0800803#ifdef CONFIG_CIFS_POSIX
Steve Frenchf9ddcca2008-05-15 05:51:55 +0000804 .unlocked_ioctl = cifs_ioctl,
Steve French8b94bcb2005-11-11 11:41:00 -0800805#endif /* CONFIG_CIFS_POSIX */
806
807#ifdef CONFIG_CIFS_EXPERIMENTAL
Steve French84210e92008-10-23 04:42:37 +0000808 .setlease = cifs_setlease,
Steve French8b94bcb2005-11-11 11:41:00 -0800809#endif /* CONFIG_CIFS_EXPERIMENTAL */
810};
811
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800812const struct file_operations cifs_file_direct_nobrl_ops = {
Steve French50c2f752007-07-13 00:33:32 +0000813 /* no mmap, no aio, no readv -
Steve French87c89dd2005-11-17 17:03:00 -0800814 BB reevaluate whether they can be done with directio, no cache */
815 .read = cifs_user_read,
816 .write = cifs_user_write,
817 .open = cifs_open,
818 .release = cifs_close,
819 .fsync = cifs_fsync,
820 .flush = cifs_flush,
Pavel Shilovsky810627a02010-03-27 02:00:49 +0000821 .mmap = cifs_file_mmap,
Jens Axboe5ffc4ef2007-06-01 11:49:19 +0200822 .splice_read = generic_file_splice_read,
Steve French8b94bcb2005-11-11 11:41:00 -0800823#ifdef CONFIG_CIFS_POSIX
Steve Frenchf9ddcca2008-05-15 05:51:55 +0000824 .unlocked_ioctl = cifs_ioctl,
Steve French8b94bcb2005-11-11 11:41:00 -0800825#endif /* CONFIG_CIFS_POSIX */
Steve Frenchc32a0b62006-01-12 14:41:28 -0800826 .llseek = cifs_llseek,
Steve French8b94bcb2005-11-11 11:41:00 -0800827#ifdef CONFIG_CIFS_EXPERIMENTAL
Steve French84210e92008-10-23 04:42:37 +0000828 .setlease = cifs_setlease,
Steve French8b94bcb2005-11-11 11:41:00 -0800829#endif /* CONFIG_CIFS_EXPERIMENTAL */
830};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800832const struct file_operations cifs_dir_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 .readdir = cifs_readdir,
834 .release = cifs_closedir,
835 .read = generic_read_dir,
Steve Frenchf9ddcca2008-05-15 05:51:55 +0000836 .unlocked_ioctl = cifs_ioctl,
Christoph Hellwig3222a3e2008-09-03 21:53:01 +0200837 .llseek = generic_file_llseek,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838};
839
840static void
Alexey Dobriyan51cc5062008-07-25 19:45:34 -0700841cifs_init_once(void *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842{
843 struct cifsInodeInfo *cifsi = inode;
844
Christoph Lametera35afb82007-05-16 22:10:57 -0700845 inode_init_once(&cifsi->vfs_inode);
846 INIT_LIST_HEAD(&cifsi->lockList);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847}
848
849static int
850cifs_init_inodecache(void)
851{
852 cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
Steve French26f57362007-08-30 22:09:15 +0000853 sizeof(struct cifsInodeInfo),
Paul Jacksonfffb60f2006-03-24 03:16:06 -0800854 0, (SLAB_RECLAIM_ACCOUNT|
855 SLAB_MEM_SPREAD),
Paul Mundt20c2df82007-07-20 10:11:58 +0900856 cifs_init_once);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 if (cifs_inode_cachep == NULL)
858 return -ENOMEM;
859
860 return 0;
861}
862
863static void
864cifs_destroy_inodecache(void)
865{
Alexey Dobriyan1a1d92c2006-09-27 01:49:40 -0700866 kmem_cache_destroy(cifs_inode_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867}
868
869static int
870cifs_init_request_bufs(void)
871{
Steve French4523cc32007-04-30 20:13:06 +0000872 if (CIFSMaxBufSize < 8192) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 /* Buffer size can not be smaller than 2 * PATH_MAX since maximum
874 Unicode path name has to fit in any SMB/CIFS path based frames */
875 CIFSMaxBufSize = 8192;
876 } else if (CIFSMaxBufSize > 1024*127) {
877 CIFSMaxBufSize = 1024 * 127;
878 } else {
879 CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/
880 }
881/* cERROR(1,("CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize)); */
882 cifs_req_cachep = kmem_cache_create("cifs_request",
883 CIFSMaxBufSize +
884 MAX_CIFS_HDR_SIZE, 0,
Paul Mundt20c2df82007-07-20 10:11:58 +0900885 SLAB_HWCACHE_ALIGN, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 if (cifs_req_cachep == NULL)
887 return -ENOMEM;
888
Steve French4523cc32007-04-30 20:13:06 +0000889 if (cifs_min_rcv < 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 cifs_min_rcv = 1;
891 else if (cifs_min_rcv > 64) {
892 cifs_min_rcv = 64;
Steve French50c2f752007-07-13 00:33:32 +0000893 cERROR(1, ("cifs_min_rcv set to maximum (64)"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 }
895
Matthew Dobson93d23412006-03-26 01:37:50 -0800896 cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv,
897 cifs_req_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898
Steve French4523cc32007-04-30 20:13:06 +0000899 if (cifs_req_poolp == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 kmem_cache_destroy(cifs_req_cachep);
901 return -ENOMEM;
902 }
Steve Frenchec637e32005-12-12 20:53:18 -0800903 /* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 almost all handle based requests (but not write response, nor is it
905 sufficient for path based requests). A smaller size would have
Steve French50c2f752007-07-13 00:33:32 +0000906 been more efficient (compacting multiple slab items on one 4k page)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 for the case in which debug was on, but this larger size allows
908 more SMBs to use small buffer alloc and is still much more
Steve French6dc0f872007-07-06 23:13:06 +0000909 efficient to alloc 1 per page off the slab compared to 17K (5page)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 alloc of large cifs buffers even when page debugging is on */
911 cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq",
Steve French6dc0f872007-07-06 23:13:06 +0000912 MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN,
Paul Mundt20c2df82007-07-20 10:11:58 +0900913 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 if (cifs_sm_req_cachep == NULL) {
915 mempool_destroy(cifs_req_poolp);
916 kmem_cache_destroy(cifs_req_cachep);
Steve French6dc0f872007-07-06 23:13:06 +0000917 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 }
919
Steve French4523cc32007-04-30 20:13:06 +0000920 if (cifs_min_small < 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 cifs_min_small = 2;
922 else if (cifs_min_small > 256) {
923 cifs_min_small = 256;
Steve French6dc0f872007-07-06 23:13:06 +0000924 cFYI(1, ("cifs_min_small set to maximum (256)"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 }
926
Matthew Dobson93d23412006-03-26 01:37:50 -0800927 cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small,
928 cifs_sm_req_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929
Steve French4523cc32007-04-30 20:13:06 +0000930 if (cifs_sm_req_poolp == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 mempool_destroy(cifs_req_poolp);
932 kmem_cache_destroy(cifs_req_cachep);
933 kmem_cache_destroy(cifs_sm_req_cachep);
934 return -ENOMEM;
935 }
936
937 return 0;
938}
939
940static void
941cifs_destroy_request_bufs(void)
942{
943 mempool_destroy(cifs_req_poolp);
Alexey Dobriyan1a1d92c2006-09-27 01:49:40 -0700944 kmem_cache_destroy(cifs_req_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 mempool_destroy(cifs_sm_req_poolp);
Alexey Dobriyan1a1d92c2006-09-27 01:49:40 -0700946 kmem_cache_destroy(cifs_sm_req_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947}
948
949static int
950cifs_init_mids(void)
951{
952 cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
Steve French26f57362007-08-30 22:09:15 +0000953 sizeof(struct mid_q_entry), 0,
954 SLAB_HWCACHE_ALIGN, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 if (cifs_mid_cachep == NULL)
956 return -ENOMEM;
957
Matthew Dobson93d23412006-03-26 01:37:50 -0800958 /* 3 is a reasonable minimum number of simultaneous operations */
959 cifs_mid_poolp = mempool_create_slab_pool(3, cifs_mid_cachep);
Steve French4523cc32007-04-30 20:13:06 +0000960 if (cifs_mid_poolp == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 kmem_cache_destroy(cifs_mid_cachep);
962 return -ENOMEM;
963 }
964
965 cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs",
Steve French26f57362007-08-30 22:09:15 +0000966 sizeof(struct oplock_q_entry), 0,
967 SLAB_HWCACHE_ALIGN, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 if (cifs_oplock_cachep == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 mempool_destroy(cifs_mid_poolp);
Akinobu Mitae6985c72007-06-04 16:14:59 +0000970 kmem_cache_destroy(cifs_mid_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 return -ENOMEM;
972 }
973
974 return 0;
975}
976
977static void
978cifs_destroy_mids(void)
979{
980 mempool_destroy(cifs_mid_poolp);
Alexey Dobriyan1a1d92c2006-09-27 01:49:40 -0700981 kmem_cache_destroy(cifs_mid_cachep);
982 kmem_cache_destroy(cifs_oplock_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983}
984
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985static int __init
986init_cifs(void)
987{
988 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 cifs_proc_init();
Jeff Laytone7ddee92008-11-14 13:44:38 -0500990 INIT_LIST_HEAD(&cifs_tcp_ses_list);
Steve French4ca9c192005-10-10 19:52:13 -0700991#ifdef CONFIG_CIFS_EXPERIMENTAL
992 INIT_LIST_HEAD(&GlobalDnotifyReqList);
993 INIT_LIST_HEAD(&GlobalDnotifyRsp_Q);
Steve French6dc0f872007-07-06 23:13:06 +0000994#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995/*
996 * Initialize Global counters
997 */
998 atomic_set(&sesInfoAllocCount, 0);
999 atomic_set(&tconInfoAllocCount, 0);
Steve French6dc0f872007-07-06 23:13:06 +00001000 atomic_set(&tcpSesAllocCount, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 atomic_set(&tcpSesReconnectCount, 0);
1002 atomic_set(&tconInfoReconnectCount, 0);
1003
1004 atomic_set(&bufAllocCount, 0);
Steve French4498eed52005-12-03 13:58:57 -08001005 atomic_set(&smBufAllocCount, 0);
1006#ifdef CONFIG_CIFS_STATS2
1007 atomic_set(&totBufAllocCount, 0);
1008 atomic_set(&totSmBufAllocCount, 0);
1009#endif /* CONFIG_CIFS_STATS2 */
1010
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 atomic_set(&midCount, 0);
1012 GlobalCurrentXid = 0;
1013 GlobalTotalActiveXid = 0;
1014 GlobalMaxActiveXid = 0;
Steve French2cd646a2006-09-28 19:43:08 +00001015 memset(Local_System_Name, 0, 15);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 rwlock_init(&GlobalSMBSeslock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05001017 rwlock_init(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 spin_lock_init(&GlobalMid_Lock);
1019
Steve French4523cc32007-04-30 20:13:06 +00001020 if (cifs_max_pending < 2) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 cifs_max_pending = 2;
Steve French6dc0f872007-07-06 23:13:06 +00001022 cFYI(1, ("cifs_max_pending set to min of 2"));
Steve French4523cc32007-04-30 20:13:06 +00001023 } else if (cifs_max_pending > 256) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 cifs_max_pending = 256;
Steve French6dc0f872007-07-06 23:13:06 +00001025 cFYI(1, ("cifs_max_pending set to max of 256"));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 }
1027
1028 rc = cifs_init_inodecache();
Steve French45af7a02006-04-21 22:52:25 +00001029 if (rc)
1030 goto out_clean_proc;
1031
1032 rc = cifs_init_mids();
1033 if (rc)
1034 goto out_destroy_inodecache;
1035
1036 rc = cifs_init_request_bufs();
1037 if (rc)
1038 goto out_destroy_mids;
1039
1040 rc = register_filesystem(&cifs_fs_type);
1041 if (rc)
1042 goto out_destroy_request_bufs;
Jeff Layton84a15b92007-11-03 05:02:24 +00001043#ifdef CONFIG_CIFS_UPCALL
1044 rc = register_key_type(&cifs_spnego_key_type);
1045 if (rc)
1046 goto out_unregister_filesystem;
1047#endif
Steve French61033352008-01-09 16:21:36 +00001048#ifdef CONFIG_CIFS_DFS_UPCALL
1049 rc = register_key_type(&key_type_dns_resolver);
1050 if (rc)
1051 goto out_unregister_key_type;
1052#endif
David Howells0109d7e2009-11-20 21:50:36 +00001053 rc = slow_work_register_user(THIS_MODULE);
Jeff Layton3bc303c2009-09-21 06:47:50 -04001054 if (rc)
1055 goto out_unregister_resolver_key;
Steve French45af7a02006-04-21 22:52:25 +00001056
Steve French45af7a02006-04-21 22:52:25 +00001057 return 0;
1058
Jeff Layton3bc303c2009-09-21 06:47:50 -04001059 out_unregister_resolver_key:
Steve French61033352008-01-09 16:21:36 +00001060#ifdef CONFIG_CIFS_DFS_UPCALL
1061 unregister_key_type(&key_type_dns_resolver);
Jeff Layton84a15b92007-11-03 05:02:24 +00001062 out_unregister_key_type:
Steve French61033352008-01-09 16:21:36 +00001063#endif
Jeff Layton84a15b92007-11-03 05:02:24 +00001064#ifdef CONFIG_CIFS_UPCALL
1065 unregister_key_type(&cifs_spnego_key_type);
Steve French45af7a02006-04-21 22:52:25 +00001066 out_unregister_filesystem:
Jeff Layton84a15b92007-11-03 05:02:24 +00001067#endif
Steve French45af7a02006-04-21 22:52:25 +00001068 unregister_filesystem(&cifs_fs_type);
1069 out_destroy_request_bufs:
1070 cifs_destroy_request_bufs();
1071 out_destroy_mids:
1072 cifs_destroy_mids();
1073 out_destroy_inodecache:
1074 cifs_destroy_inodecache();
1075 out_clean_proc:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 cifs_proc_clean();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 return rc;
1078}
1079
1080static void __exit
1081exit_cifs(void)
1082{
Steve French90c81e02008-02-12 20:32:36 +00001083 cFYI(DBG2, ("exit_cifs"));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 cifs_proc_clean();
Steve French61033352008-01-09 16:21:36 +00001085#ifdef CONFIG_CIFS_DFS_UPCALL
Igor Mammedov78d31a32008-04-24 12:56:07 +04001086 cifs_dfs_release_automount_timer();
Steve French61033352008-01-09 16:21:36 +00001087 unregister_key_type(&key_type_dns_resolver);
1088#endif
Jeff Layton84a15b92007-11-03 05:02:24 +00001089#ifdef CONFIG_CIFS_UPCALL
1090 unregister_key_type(&cifs_spnego_key_type);
1091#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 unregister_filesystem(&cifs_fs_type);
1093 cifs_destroy_inodecache();
1094 cifs_destroy_mids();
1095 cifs_destroy_request_bufs();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096}
1097
1098MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
Steve French6dc0f872007-07-06 23:13:06 +00001099MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100MODULE_DESCRIPTION
Steve French63135e02007-07-17 17:34:02 +00001101 ("VFS to access servers complying with the SNIA CIFS Specification "
1102 "e.g. Samba and Windows");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103MODULE_VERSION(CIFS_VERSION);
1104module_init(init_cifs)
1105module_exit(exit_cifs)