blob: 887c89b43bd8a917c81e4f5e2e833f4b2abce044 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/cifsfs.c
3 *
4 * Copyright (C) International Business Machines Corp., 2002,2004
5 * 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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include "cifsfs.h"
39#include "cifspdu.h"
40#define DECLARE_GLOBALS_HERE
41#include "cifsglob.h"
42#include "cifsproto.h"
43#include "cifs_debug.h"
44#include "cifs_fs_sb.h"
45#include <linux/mm.h>
46#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
47
48#ifdef CONFIG_CIFS_QUOTA
49static struct quotactl_ops cifs_quotactl_ops;
50#endif
51
52int cifsFYI = 0;
53int cifsERROR = 1;
54int traceSMB = 0;
55unsigned int oplockEnabled = 1;
56unsigned int experimEnabled = 0;
57unsigned int linuxExtEnabled = 1;
58unsigned int lookupCacheEnabled = 1;
59unsigned int multiuser_mount = 0;
Steve French39798772006-05-31 22:40:51 +000060unsigned int extended_security = CIFSSEC_DEF;
61/* unsigned int ntlmv2_support = 0; */
Linus Torvalds1da177e2005-04-16 15:20:36 -070062unsigned int sign_CIFS_PDUs = 1;
63extern struct task_struct * oplockThread; /* remove sparse warning */
64struct task_struct * oplockThread = NULL;
Steve French8d0d5092005-08-18 09:41:43 -070065extern struct task_struct * dnotifyThread; /* remove sparse warning */
66struct task_struct * dnotifyThread = NULL;
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);
70MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048");
71unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
72module_param(cifs_min_rcv, int, 0);
73MODULE_PARM_DESC(cifs_min_rcv,"Network buffers in pool. Default: 4 Range: 1 to 64");
74unsigned int cifs_min_small = 30;
75module_param(cifs_min_small, int, 0);
76MODULE_PARM_DESC(cifs_min_small,"Small network buffers in pool. Default: 30 Range: 2 to 256");
77unsigned int cifs_max_pending = CIFS_MAX_REQ;
78module_param(cifs_max_pending, int, 0);
79MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256");
80
Linus Torvalds1da177e2005-04-16 15:20:36 -070081extern mempool_t *cifs_sm_req_poolp;
82extern mempool_t *cifs_req_poolp;
83extern mempool_t *cifs_mid_poolp;
84
Christoph Lametere18b8902006-12-06 20:33:20 -080085extern struct kmem_cache *cifs_oplock_cachep;
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
87static int
88cifs_read_super(struct super_block *sb, void *data,
89 const char *devname, int silent)
90{
91 struct inode *inode;
92 struct cifs_sb_info *cifs_sb;
93 int rc = 0;
Steve French1b2b2122007-02-17 04:30:54 +000094
95 /* BB should we make this contingent on mount parm? */
96 sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
Eric Sesterhenna048d7a2006-02-21 22:33:09 +000097 sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 cifs_sb = CIFS_SB(sb);
99 if(cifs_sb == NULL)
100 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
102 rc = cifs_mount(sb, cifs_sb, data, devname);
103
104 if (rc) {
105 if (!silent)
106 cERROR(1,
107 ("cifs_mount failed w/return code = %d", rc));
108 goto out_mount_failed;
109 }
110
111 sb->s_magic = CIFS_MAGIC_NUMBER;
112 sb->s_op = &cifs_super_ops;
113/* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
114 sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
115#ifdef CONFIG_CIFS_QUOTA
116 sb->s_qcop = &cifs_quotactl_ops;
117#endif
118 sb->s_blocksize = CIFS_MAX_MSGSIZE;
119 sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
120 inode = iget(sb, ROOT_I);
121
122 if (!inode) {
123 rc = -ENOMEM;
124 goto out_no_root;
125 }
126
127 sb->s_root = d_alloc_root(inode);
128
129 if (!sb->s_root) {
130 rc = -ENOMEM;
131 goto out_no_root;
132 }
133
134 return 0;
135
136out_no_root:
137 cERROR(1, ("cifs_read_super: get root inode failed"));
138 if (inode)
139 iput(inode);
140
141out_mount_failed:
142 if(cifs_sb) {
143 if(cifs_sb->local_nls)
144 unload_nls(cifs_sb->local_nls);
145 kfree(cifs_sb);
146 }
147 return rc;
148}
149
150static void
151cifs_put_super(struct super_block *sb)
152{
153 int rc = 0;
154 struct cifs_sb_info *cifs_sb;
155
156 cFYI(1, ("In cifs_put_super"));
157 cifs_sb = CIFS_SB(sb);
158 if(cifs_sb == NULL) {
159 cFYI(1,("Empty cifs superblock info passed to unmount"));
160 return;
161 }
162 rc = cifs_umount(sb, cifs_sb);
163 if (rc) {
164 cERROR(1, ("cifs_umount failed with return code %d", rc));
165 }
166 unload_nls(cifs_sb->local_nls);
167 kfree(cifs_sb);
168 return;
169}
170
171static int
David Howells726c3342006-06-23 02:02:58 -0700172cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173{
David Howells726c3342006-06-23 02:02:58 -0700174 struct super_block *sb = dentry->d_sb;
Steve Frenchc81156d2005-04-28 22:41:07 -0700175 int xid;
176 int rc = -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 struct cifs_sb_info *cifs_sb;
178 struct cifsTconInfo *pTcon;
179
180 xid = GetXid();
181
182 cifs_sb = CIFS_SB(sb);
183 pTcon = cifs_sb->tcon;
184
185 buf->f_type = CIFS_MAGIC_NUMBER;
186
187 /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */
Steve Frenchc81156d2005-04-28 22:41:07 -0700188 buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would
189 presumably be total path, but note
190 that some servers (includinng Samba 3)
191 have a shorter maximum path */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 buf->f_files = 0; /* undefined */
193 buf->f_ffree = 0; /* unlimited */
194
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195/* BB we could add a second check for a QFS Unix capability bit */
Steve Frenchf28ac912005-04-28 22:41:07 -0700196/* BB FIXME check CIFS_POSIX_EXTENSIONS Unix cap first FIXME BB */
Steve Frenchc81156d2005-04-28 22:41:07 -0700197 if ((pTcon->ses->capabilities & CAP_UNIX) && (CIFS_POSIX_EXTENSIONS &
198 le64_to_cpu(pTcon->fsUnixInfo.Capability)))
Steve French737b7582005-04-28 22:41:06 -0700199 rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
201 /* Only need to call the old QFSInfo if failed
202 on newer one */
203 if(rc)
Steve Frenchde7ed552006-09-30 13:25:52 +0000204 if(pTcon->ses->capabilities & CAP_NT_SMBS)
Steve French9ac00b72006-09-30 04:13:17 +0000205 rc = CIFSSMBQFSInfo(xid, pTcon, buf); /* not supported by OS2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206
Steve French9ac00b72006-09-30 04:13:17 +0000207 /* Some old Windows servers also do not support level 103, retry with
208 older level one if old server failed the previous call or we
209 bypassed it because we detected that this was an older LANMAN sess */
Steve French20962432005-09-21 22:05:57 -0700210 if(rc)
211 rc = SMBOldQFSInfo(xid, pTcon, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 /*
213 int f_type;
214 __fsid_t f_fsid;
215 int f_namelen; */
Steve Frenchc81156d2005-04-28 22:41:07 -0700216 /* BB get from info in tcon struct at mount time call to QFSAttrInfo */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 FreeXid(xid);
Steve Frenchc81156d2005-04-28 22:41:07 -0700218 return 0; /* always return success? what if volume is no
219 longer available? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220}
221
222static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
223{
224 struct cifs_sb_info *cifs_sb;
225
226 cifs_sb = CIFS_SB(inode->i_sb);
227
228 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
229 return 0;
230 } else /* file mode might have been restricted at mount time
231 on the client (above and beyond ACL on servers) for
232 servers which do not support setting and viewing mode bits,
233 so allowing client to check permissions is useful */
234 return generic_permission(inode, mask, NULL);
235}
236
Christoph Lametere18b8902006-12-06 20:33:20 -0800237static struct kmem_cache *cifs_inode_cachep;
238static struct kmem_cache *cifs_req_cachep;
239static struct kmem_cache *cifs_mid_cachep;
240struct kmem_cache *cifs_oplock_cachep;
241static struct kmem_cache *cifs_sm_req_cachep;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242mempool_t *cifs_sm_req_poolp;
243mempool_t *cifs_req_poolp;
244mempool_t *cifs_mid_poolp;
245
246static struct inode *
247cifs_alloc_inode(struct super_block *sb)
248{
249 struct cifsInodeInfo *cifs_inode;
Christoph Lametere94b1762006-12-06 20:33:17 -0800250 cifs_inode = kmem_cache_alloc(cifs_inode_cachep, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 if (!cifs_inode)
252 return NULL;
253 cifs_inode->cifsAttrs = 0x20; /* default */
254 atomic_set(&cifs_inode->inUse, 0);
255 cifs_inode->time = 0;
256 /* Until the file is open and we have gotten oplock
257 info back from the server, can not assume caching of
258 file data or metadata */
259 cifs_inode->clientCanCacheRead = FALSE;
260 cifs_inode->clientCanCacheAll = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
Steve French1b2b2122007-02-17 04:30:54 +0000262
263 /* Can not set i_flags here - they get immediately overwritten
264 to zero by the VFS */
265/* cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 INIT_LIST_HEAD(&cifs_inode->openFileList);
267 return &cifs_inode->vfs_inode;
268}
269
270static void
271cifs_destroy_inode(struct inode *inode)
272{
273 kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
274}
275
276/*
277 * cifs_show_options() is for displaying mount options in /proc/mounts.
278 * Not all settable options are displayed but most of the important
279 * ones are.
280 */
281static int
282cifs_show_options(struct seq_file *s, struct vfsmount *m)
283{
284 struct cifs_sb_info *cifs_sb;
285
286 cifs_sb = CIFS_SB(m->mnt_sb);
287
288 if (cifs_sb) {
289 if (cifs_sb->tcon) {
290 seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
291 if (cifs_sb->tcon->ses) {
292 if (cifs_sb->tcon->ses->userName)
293 seq_printf(s, ",username=%s",
294 cifs_sb->tcon->ses->userName);
295 if(cifs_sb->tcon->ses->domainName)
296 seq_printf(s, ",domain=%s",
297 cifs_sb->tcon->ses->domainName);
298 }
299 }
300 seq_printf(s, ",rsize=%d",cifs_sb->rsize);
301 seq_printf(s, ",wsize=%d",cifs_sb->wsize);
302 }
303 return 0;
304}
305
306#ifdef CONFIG_CIFS_QUOTA
307int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
308 struct fs_disk_quota * pdquota)
309{
310 int xid;
311 int rc = 0;
312 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
313 struct cifsTconInfo *pTcon;
314
315 if(cifs_sb)
316 pTcon = cifs_sb->tcon;
317 else
318 return -EIO;
319
320
321 xid = GetXid();
322 if(pTcon) {
323 cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
324 } else {
325 return -EIO;
326 }
327
328 FreeXid(xid);
329 return rc;
330}
331
332int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
333 struct fs_disk_quota * pdquota)
334{
335 int xid;
336 int rc = 0;
337 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
338 struct cifsTconInfo *pTcon;
339
340 if(cifs_sb)
341 pTcon = cifs_sb->tcon;
342 else
343 return -EIO;
344
345 xid = GetXid();
346 if(pTcon) {
347 cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
348 } else {
349 rc = -EIO;
350 }
351
352 FreeXid(xid);
353 return rc;
354}
355
356int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
357{
358 int xid;
359 int rc = 0;
360 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
361 struct cifsTconInfo *pTcon;
362
363 if(cifs_sb)
364 pTcon = cifs_sb->tcon;
365 else
366 return -EIO;
367
368 xid = GetXid();
369 if(pTcon) {
370 cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation));
371 } else {
372 rc = -EIO;
373 }
374
375 FreeXid(xid);
376 return rc;
377}
378
379int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats)
380{
381 int xid;
382 int rc = 0;
383 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
384 struct cifsTconInfo *pTcon;
385
386 if(cifs_sb) {
387 pTcon = cifs_sb->tcon;
388 } else {
389 return -EIO;
390 }
391 xid = GetXid();
392 if(pTcon) {
393 cFYI(1,("pqstats %p",qstats));
394 } else {
395 rc = -EIO;
396 }
397
398 FreeXid(xid);
399 return rc;
400}
401
402static struct quotactl_ops cifs_quotactl_ops = {
403 .set_xquota = cifs_xquota_set,
404 .get_xquota = cifs_xquota_set,
405 .set_xstate = cifs_xstate_set,
406 .get_xstate = cifs_xstate_get,
407};
408#endif
409
Trond Myklebust8b512d92006-06-09 09:34:18 -0400410static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
Steve French68058e72005-10-10 10:34:22 -0700411{
Steve French5e1253b2005-10-10 14:06:37 -0700412 struct cifs_sb_info *cifs_sb;
Steve French9e2e85f2005-10-10 14:28:38 -0700413 struct cifsTconInfo * tcon;
Steve French68058e72005-10-10 10:34:22 -0700414
Trond Myklebust8b512d92006-06-09 09:34:18 -0400415 if (!(flags & MNT_FORCE))
416 return;
417 cifs_sb = CIFS_SB(vfsmnt->mnt_sb);
Steve French5e1253b2005-10-10 14:06:37 -0700418 if(cifs_sb == NULL)
Steve French9e2e85f2005-10-10 14:28:38 -0700419 return;
420
421 tcon = cifs_sb->tcon;
422 if(tcon == NULL)
423 return;
Steve French5e1253b2005-10-10 14:06:37 -0700424 down(&tcon->tconSem);
425 if (atomic_read(&tcon->useCount) == 1)
426 tcon->tidStatus = CifsExiting;
427 up(&tcon->tconSem);
428
Steve French3a5ff612006-07-14 22:37:11 +0000429 /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
Steve French7b7abfe2005-11-09 15:21:09 -0800430 /* cancel_notify_requests(tcon); */
Steve French9e2e85f2005-10-10 14:28:38 -0700431 if(tcon->ses && tcon->ses->server)
Steve French5e1253b2005-10-10 14:06:37 -0700432 {
Steve French7b7abfe2005-11-09 15:21:09 -0800433 cFYI(1,("wake up tasks now - umount begin not complete"));
Steve French9e2e85f2005-10-10 14:28:38 -0700434 wake_up_all(&tcon->ses->server->request_q);
Steve French6ab16d22005-11-29 20:55:11 -0800435 wake_up_all(&tcon->ses->server->response_q);
436 msleep(1); /* yield */
437 /* we have to kick the requests once more */
438 wake_up_all(&tcon->ses->server->response_q);
439 msleep(1);
Steve French5e1253b2005-10-10 14:06:37 -0700440 }
441/* BB FIXME - finish add checks for tidStatus BB */
Steve French68058e72005-10-10 10:34:22 -0700442
443 return;
444}
Steve French68058e72005-10-10 10:34:22 -0700445
Steve Frenchbf97d282006-09-28 21:34:06 +0000446#ifdef CONFIG_CIFS_STATS2
447static int cifs_show_stats(struct seq_file *s, struct vfsmount *mnt)
448{
449 /* BB FIXME */
450 return 0;
451}
452#endif
453
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454static int cifs_remount(struct super_block *sb, int *flags, char *data)
455{
456 *flags |= MS_NODIRATIME;
457 return 0;
458}
459
Josef 'Jeff' Sipekee9b6d62007-02-12 00:55:41 -0800460static const struct super_operations cifs_super_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 .read_inode = cifs_read_inode,
462 .put_super = cifs_put_super,
463 .statfs = cifs_statfs,
464 .alloc_inode = cifs_alloc_inode,
465 .destroy_inode = cifs_destroy_inode,
466/* .drop_inode = generic_delete_inode,
467 .delete_inode = cifs_delete_inode, *//* Do not need the above two functions
468 unless later we add lazy close of inodes or unless the kernel forgets to call
469 us with the same number of releases (closes) as opens */
470 .show_options = cifs_show_options,
Steve French7b7abfe2005-11-09 15:21:09 -0800471 .umount_begin = cifs_umount_begin,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 .remount_fs = cifs_remount,
Steve Frenchbf97d282006-09-28 21:34:06 +0000473#ifdef CONFIG_CIFS_STATS2
Steve Frenchf46d3e12006-09-30 01:08:55 +0000474 .show_stats = cifs_show_stats,
Steve Frenchbf97d282006-09-28 21:34:06 +0000475#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476};
477
David Howells454e2392006-06-23 02:02:57 -0700478static int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479cifs_get_sb(struct file_system_type *fs_type,
David Howells454e2392006-06-23 02:02:57 -0700480 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481{
482 int rc;
483 struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
484
485 cFYI(1, ("Devname: %s flags: %d ", dev_name, flags));
486
487 if (IS_ERR(sb))
David Howells454e2392006-06-23 02:02:57 -0700488 return PTR_ERR(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489
490 sb->s_flags = flags;
491
Theodore Ts'o9b04c992006-03-24 03:15:10 -0800492 rc = cifs_read_super(sb, data, dev_name, flags & MS_SILENT ? 1 : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 if (rc) {
494 up_write(&sb->s_umount);
495 deactivate_super(sb);
David Howells454e2392006-06-23 02:02:57 -0700496 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 }
498 sb->s_flags |= MS_ACTIVE;
David Howells454e2392006-06-23 02:02:57 -0700499 return simple_set_mnt(mnt, sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500}
501
Badari Pulavarty027445c2006-09-30 23:28:46 -0700502static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
503 unsigned long nr_segs, loff_t pos)
Steve French87c89dd2005-11-17 17:03:00 -0800504{
Josef "Jeff" Sipeke6a00292006-12-08 02:36:48 -0800505 struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
Steve French87c89dd2005-11-17 17:03:00 -0800506 ssize_t written;
507
Badari Pulavarty027445c2006-09-30 23:28:46 -0700508 written = generic_file_aio_write(iocb, iov, nr_segs, pos);
Steve French87c89dd2005-11-17 17:03:00 -0800509 if (!CIFS_I(inode)->clientCanCacheAll)
510 filemap_fdatawrite(inode->i_mapping);
511 return written;
512}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513
Steve Frenchc32a0b62006-01-12 14:41:28 -0800514static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
515{
516 /* origin == SEEK_END => we must revalidate the cached file length */
Steve French0889a942006-09-23 22:11:07 +0000517 if (origin == SEEK_END) {
Steve French030e9d82007-02-01 04:27:59 +0000518 int retval;
519
520 /* some applications poll for the file length in this strange
521 way so we must seek to end on non-oplocked files by
522 setting the revalidate time to zero */
523 if(file->f_path.dentry->d_inode)
524 CIFS_I(file->f_path.dentry->d_inode)->time = 0;
525
526 retval = cifs_revalidate(file->f_path.dentry);
Steve Frenchc32a0b62006-01-12 14:41:28 -0800527 if (retval < 0)
528 return (loff_t)retval;
529 }
530 return remote_llseek(file, offset, origin);
531}
532
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533static struct file_system_type cifs_fs_type = {
534 .owner = THIS_MODULE,
535 .name = "cifs",
536 .get_sb = cifs_get_sb,
537 .kill_sb = kill_anon_super,
538 /* .fs_flags */
539};
Arjan van de Ven754661f2007-02-12 00:55:38 -0800540const struct inode_operations cifs_dir_inode_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 .create = cifs_create,
542 .lookup = cifs_lookup,
543 .getattr = cifs_getattr,
544 .unlink = cifs_unlink,
545 .link = cifs_hardlink,
546 .mkdir = cifs_mkdir,
547 .rmdir = cifs_rmdir,
548 .rename = cifs_rename,
549 .permission = cifs_permission,
550/* revalidate:cifs_revalidate, */
551 .setattr = cifs_setattr,
552 .symlink = cifs_symlink,
553 .mknod = cifs_mknod,
554#ifdef CONFIG_CIFS_XATTR
555 .setxattr = cifs_setxattr,
556 .getxattr = cifs_getxattr,
557 .listxattr = cifs_listxattr,
558 .removexattr = cifs_removexattr,
559#endif
560};
561
Arjan van de Ven754661f2007-02-12 00:55:38 -0800562const struct inode_operations cifs_file_inode_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563/* revalidate:cifs_revalidate, */
564 .setattr = cifs_setattr,
565 .getattr = cifs_getattr, /* do we need this anymore? */
566 .rename = cifs_rename,
567 .permission = cifs_permission,
568#ifdef CONFIG_CIFS_XATTR
569 .setxattr = cifs_setxattr,
570 .getxattr = cifs_getxattr,
571 .listxattr = cifs_listxattr,
572 .removexattr = cifs_removexattr,
573#endif
574};
575
Arjan van de Ven754661f2007-02-12 00:55:38 -0800576const struct inode_operations cifs_symlink_inode_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 .readlink = generic_readlink,
578 .follow_link = cifs_follow_link,
579 .put_link = cifs_put_link,
580 .permission = cifs_permission,
581 /* BB add the following two eventually */
582 /* revalidate: cifs_revalidate,
583 setattr: cifs_notify_change, *//* BB do we need notify change */
584#ifdef CONFIG_CIFS_XATTR
585 .setxattr = cifs_setxattr,
586 .getxattr = cifs_getxattr,
587 .listxattr = cifs_listxattr,
588 .removexattr = cifs_removexattr,
589#endif
590};
591
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800592const struct file_operations cifs_file_ops = {
Steve French87c89dd2005-11-17 17:03:00 -0800593 .read = do_sync_read,
594 .write = do_sync_write,
Steve French87c89dd2005-11-17 17:03:00 -0800595 .aio_read = generic_file_aio_read,
596 .aio_write = cifs_file_aio_write,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 .open = cifs_open,
598 .release = cifs_close,
599 .lock = cifs_lock,
600 .fsync = cifs_fsync,
601 .flush = cifs_flush,
602 .mmap = cifs_file_mmap,
603 .sendfile = generic_file_sendfile,
Steve Frenchc32a0b62006-01-12 14:41:28 -0800604 .llseek = cifs_llseek,
Steve Frenchc67593a2005-04-28 22:41:04 -0700605#ifdef CONFIG_CIFS_POSIX
606 .ioctl = cifs_ioctl,
607#endif /* CONFIG_CIFS_POSIX */
608
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609#ifdef CONFIG_CIFS_EXPERIMENTAL
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 .dir_notify = cifs_dir_notify,
611#endif /* CONFIG_CIFS_EXPERIMENTAL */
612};
613
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800614const struct file_operations cifs_file_direct_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 /* no mmap, no aio, no readv -
616 BB reevaluate whether they can be done with directio, no cache */
617 .read = cifs_user_read,
618 .write = cifs_user_write,
619 .open = cifs_open,
620 .release = cifs_close,
621 .lock = cifs_lock,
622 .fsync = cifs_fsync,
623 .flush = cifs_flush,
624 .sendfile = generic_file_sendfile, /* BB removeme BB */
Steve Frenchc67593a2005-04-28 22:41:04 -0700625#ifdef CONFIG_CIFS_POSIX
626 .ioctl = cifs_ioctl,
627#endif /* CONFIG_CIFS_POSIX */
Steve Frenchc32a0b62006-01-12 14:41:28 -0800628 .llseek = cifs_llseek,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629#ifdef CONFIG_CIFS_EXPERIMENTAL
630 .dir_notify = cifs_dir_notify,
631#endif /* CONFIG_CIFS_EXPERIMENTAL */
632};
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800633const struct file_operations cifs_file_nobrl_ops = {
Steve French87c89dd2005-11-17 17:03:00 -0800634 .read = do_sync_read,
635 .write = do_sync_write,
Steve French87c89dd2005-11-17 17:03:00 -0800636 .aio_read = generic_file_aio_read,
637 .aio_write = cifs_file_aio_write,
638 .open = cifs_open,
639 .release = cifs_close,
640 .fsync = cifs_fsync,
641 .flush = cifs_flush,
642 .mmap = cifs_file_mmap,
643 .sendfile = generic_file_sendfile,
Steve Frenchc32a0b62006-01-12 14:41:28 -0800644 .llseek = cifs_llseek,
Steve French8b94bcb2005-11-11 11:41:00 -0800645#ifdef CONFIG_CIFS_POSIX
Steve French87c89dd2005-11-17 17:03:00 -0800646 .ioctl = cifs_ioctl,
Steve French8b94bcb2005-11-11 11:41:00 -0800647#endif /* CONFIG_CIFS_POSIX */
648
649#ifdef CONFIG_CIFS_EXPERIMENTAL
Steve French87c89dd2005-11-17 17:03:00 -0800650 .dir_notify = cifs_dir_notify,
Steve French8b94bcb2005-11-11 11:41:00 -0800651#endif /* CONFIG_CIFS_EXPERIMENTAL */
652};
653
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800654const struct file_operations cifs_file_direct_nobrl_ops = {
Steve French87c89dd2005-11-17 17:03:00 -0800655 /* no mmap, no aio, no readv -
656 BB reevaluate whether they can be done with directio, no cache */
657 .read = cifs_user_read,
658 .write = cifs_user_write,
659 .open = cifs_open,
660 .release = cifs_close,
661 .fsync = cifs_fsync,
662 .flush = cifs_flush,
663 .sendfile = generic_file_sendfile, /* BB removeme BB */
Steve French8b94bcb2005-11-11 11:41:00 -0800664#ifdef CONFIG_CIFS_POSIX
Steve French87c89dd2005-11-17 17:03:00 -0800665 .ioctl = cifs_ioctl,
Steve French8b94bcb2005-11-11 11:41:00 -0800666#endif /* CONFIG_CIFS_POSIX */
Steve Frenchc32a0b62006-01-12 14:41:28 -0800667 .llseek = cifs_llseek,
Steve French8b94bcb2005-11-11 11:41:00 -0800668#ifdef CONFIG_CIFS_EXPERIMENTAL
Steve French87c89dd2005-11-17 17:03:00 -0800669 .dir_notify = cifs_dir_notify,
Steve French8b94bcb2005-11-11 11:41:00 -0800670#endif /* CONFIG_CIFS_EXPERIMENTAL */
671};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -0800673const struct file_operations cifs_dir_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 .readdir = cifs_readdir,
675 .release = cifs_closedir,
676 .read = generic_read_dir,
677#ifdef CONFIG_CIFS_EXPERIMENTAL
678 .dir_notify = cifs_dir_notify,
679#endif /* CONFIG_CIFS_EXPERIMENTAL */
Steve Frenchf28ac912005-04-28 22:41:07 -0700680 .ioctl = cifs_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681};
682
683static void
Christoph Lametere18b8902006-12-06 20:33:20 -0800684cifs_init_once(void *inode, struct kmem_cache * cachep, unsigned long flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685{
686 struct cifsInodeInfo *cifsi = inode;
687
688 if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
689 SLAB_CTOR_CONSTRUCTOR) {
690 inode_init_once(&cifsi->vfs_inode);
691 INIT_LIST_HEAD(&cifsi->lockList);
692 }
693}
694
695static int
696cifs_init_inodecache(void)
697{
698 cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
699 sizeof (struct cifsInodeInfo),
Paul Jacksonfffb60f2006-03-24 03:16:06 -0800700 0, (SLAB_RECLAIM_ACCOUNT|
701 SLAB_MEM_SPREAD),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 cifs_init_once, NULL);
703 if (cifs_inode_cachep == NULL)
704 return -ENOMEM;
705
706 return 0;
707}
708
709static void
710cifs_destroy_inodecache(void)
711{
Alexey Dobriyan1a1d92c2006-09-27 01:49:40 -0700712 kmem_cache_destroy(cifs_inode_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713}
714
715static int
716cifs_init_request_bufs(void)
717{
718 if(CIFSMaxBufSize < 8192) {
719 /* Buffer size can not be smaller than 2 * PATH_MAX since maximum
720 Unicode path name has to fit in any SMB/CIFS path based frames */
721 CIFSMaxBufSize = 8192;
722 } else if (CIFSMaxBufSize > 1024*127) {
723 CIFSMaxBufSize = 1024 * 127;
724 } else {
725 CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/
726 }
727/* cERROR(1,("CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize)); */
728 cifs_req_cachep = kmem_cache_create("cifs_request",
729 CIFSMaxBufSize +
730 MAX_CIFS_HDR_SIZE, 0,
731 SLAB_HWCACHE_ALIGN, NULL, NULL);
732 if (cifs_req_cachep == NULL)
733 return -ENOMEM;
734
735 if(cifs_min_rcv < 1)
736 cifs_min_rcv = 1;
737 else if (cifs_min_rcv > 64) {
738 cifs_min_rcv = 64;
739 cERROR(1,("cifs_min_rcv set to maximum (64)"));
740 }
741
Matthew Dobson93d23412006-03-26 01:37:50 -0800742 cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv,
743 cifs_req_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744
745 if(cifs_req_poolp == NULL) {
746 kmem_cache_destroy(cifs_req_cachep);
747 return -ENOMEM;
748 }
Steve Frenchec637e32005-12-12 20:53:18 -0800749 /* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 almost all handle based requests (but not write response, nor is it
751 sufficient for path based requests). A smaller size would have
752 been more efficient (compacting multiple slab items on one 4k page)
753 for the case in which debug was on, but this larger size allows
754 more SMBs to use small buffer alloc and is still much more
755 efficient to alloc 1 per page off the slab compared to 17K (5page)
756 alloc of large cifs buffers even when page debugging is on */
757 cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq",
Steve Frenchec637e32005-12-12 20:53:18 -0800758 MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN,
759 NULL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 if (cifs_sm_req_cachep == NULL) {
761 mempool_destroy(cifs_req_poolp);
762 kmem_cache_destroy(cifs_req_cachep);
763 return -ENOMEM;
764 }
765
766 if(cifs_min_small < 2)
767 cifs_min_small = 2;
768 else if (cifs_min_small > 256) {
769 cifs_min_small = 256;
770 cFYI(1,("cifs_min_small set to maximum (256)"));
771 }
772
Matthew Dobson93d23412006-03-26 01:37:50 -0800773 cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small,
774 cifs_sm_req_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775
776 if(cifs_sm_req_poolp == NULL) {
777 mempool_destroy(cifs_req_poolp);
778 kmem_cache_destroy(cifs_req_cachep);
779 kmem_cache_destroy(cifs_sm_req_cachep);
780 return -ENOMEM;
781 }
782
783 return 0;
784}
785
786static void
787cifs_destroy_request_bufs(void)
788{
789 mempool_destroy(cifs_req_poolp);
Alexey Dobriyan1a1d92c2006-09-27 01:49:40 -0700790 kmem_cache_destroy(cifs_req_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 mempool_destroy(cifs_sm_req_poolp);
Alexey Dobriyan1a1d92c2006-09-27 01:49:40 -0700792 kmem_cache_destroy(cifs_sm_req_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793}
794
795static int
796cifs_init_mids(void)
797{
798 cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
799 sizeof (struct mid_q_entry), 0,
800 SLAB_HWCACHE_ALIGN, NULL, NULL);
801 if (cifs_mid_cachep == NULL)
802 return -ENOMEM;
803
Matthew Dobson93d23412006-03-26 01:37:50 -0800804 /* 3 is a reasonable minimum number of simultaneous operations */
805 cifs_mid_poolp = mempool_create_slab_pool(3, cifs_mid_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 if(cifs_mid_poolp == NULL) {
807 kmem_cache_destroy(cifs_mid_cachep);
808 return -ENOMEM;
809 }
810
811 cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs",
812 sizeof (struct oplock_q_entry), 0,
813 SLAB_HWCACHE_ALIGN, NULL, NULL);
814 if (cifs_oplock_cachep == NULL) {
815 kmem_cache_destroy(cifs_mid_cachep);
816 mempool_destroy(cifs_mid_poolp);
817 return -ENOMEM;
818 }
819
820 return 0;
821}
822
823static void
824cifs_destroy_mids(void)
825{
826 mempool_destroy(cifs_mid_poolp);
Alexey Dobriyan1a1d92c2006-09-27 01:49:40 -0700827 kmem_cache_destroy(cifs_mid_cachep);
828 kmem_cache_destroy(cifs_oplock_cachep);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829}
830
831static int cifs_oplock_thread(void * dummyarg)
832{
833 struct oplock_q_entry * oplock_item;
834 struct cifsTconInfo *pTcon;
835 struct inode * inode;
836 __u16 netfid;
837 int rc;
838
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 do {
Steve Frenchede13272005-08-30 20:10:14 -0700840 if (try_to_freeze())
841 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 spin_lock(&GlobalMid_Lock);
844 if(list_empty(&GlobalOplock_Q)) {
845 spin_unlock(&GlobalMid_Lock);
846 set_current_state(TASK_INTERRUPTIBLE);
847 schedule_timeout(39*HZ);
848 } else {
849 oplock_item = list_entry(GlobalOplock_Q.next,
850 struct oplock_q_entry, qhead);
851 if(oplock_item) {
852 cFYI(1,("found oplock item to write out"));
853 pTcon = oplock_item->tcon;
854 inode = oplock_item->pinode;
855 netfid = oplock_item->netfid;
856 spin_unlock(&GlobalMid_Lock);
857 DeleteOplockQEntry(oplock_item);
858 /* can not grab inode sem here since it would
859 deadlock when oplock received on delete
Jes Sorensen1b1dcc12006-01-09 15:59:24 -0800860 since vfs_unlink holds the i_mutex across
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 the call */
Jes Sorensen1b1dcc12006-01-09 15:59:24 -0800862 /* mutex_lock(&inode->i_mutex);*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 if (S_ISREG(inode->i_mode)) {
864 rc = filemap_fdatawrite(inode->i_mapping);
865 if(CIFS_I(inode)->clientCanCacheRead == 0) {
866 filemap_fdatawait(inode->i_mapping);
867 invalidate_remote_inode(inode);
868 }
869 } else
870 rc = 0;
Jes Sorensen1b1dcc12006-01-09 15:59:24 -0800871 /* mutex_unlock(&inode->i_mutex);*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 if (rc)
873 CIFS_I(inode)->write_behind_rc = rc;
874 cFYI(1,("Oplock flush inode %p rc %d",inode,rc));
875
876 /* releasing a stale oplock after recent reconnection
877 of smb session using a now incorrect file
878 handle is not a data integrity issue but do
879 not bother sending an oplock release if session
880 to server still is disconnected since oplock
881 already released by the server in that case */
882 if(pTcon->tidStatus != CifsNeedReconnect) {
883 rc = CIFSSMBLock(0, pTcon, netfid,
884 0 /* len */ , 0 /* offset */, 0,
885 0, LOCKING_ANDX_OPLOCK_RELEASE,
886 0 /* wait flag */);
887 cFYI(1,("Oplock release rc = %d ",rc));
888 }
889 } else
890 spin_unlock(&GlobalMid_Lock);
Steve French68058e72005-10-10 10:34:22 -0700891 set_current_state(TASK_INTERRUPTIBLE);
892 schedule_timeout(1); /* yield in case q were corrupt */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 }
Steve French45af7a02006-04-21 22:52:25 +0000894 } while (!kthread_should_stop());
895
896 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897}
898
Steve French8d0d5092005-08-18 09:41:43 -0700899static int cifs_dnotify_thread(void * dummyarg)
900{
Steve French6ab16d22005-11-29 20:55:11 -0800901 struct list_head *tmp;
902 struct cifsSesInfo *ses;
903
Steve French8d0d5092005-08-18 09:41:43 -0700904 do {
Pavel Machek0fd1ffe2006-06-13 21:31:39 +0000905 if (try_to_freeze())
Steve French16abbec2005-08-30 13:10:14 -0700906 continue;
Steve French8d0d5092005-08-18 09:41:43 -0700907 set_current_state(TASK_INTERRUPTIBLE);
Steve French6ab16d22005-11-29 20:55:11 -0800908 schedule_timeout(15*HZ);
909 read_lock(&GlobalSMBSeslock);
910 /* check if any stuck requests that need
911 to be woken up and wakeq so the
912 thread can wake up and error out */
913 list_for_each(tmp, &GlobalSMBSessionList) {
914 ses = list_entry(tmp, struct cifsSesInfo,
915 cifsSessionList);
916 if(ses && ses->server &&
Steve French2a138ebb2005-11-29 21:22:19 -0800917 atomic_read(&ses->server->inFlight))
Steve French6ab16d22005-11-29 20:55:11 -0800918 wake_up_all(&ses->server->response_q);
919 }
920 read_unlock(&GlobalSMBSeslock);
Steve French45af7a02006-04-21 22:52:25 +0000921 } while (!kthread_should_stop());
922
923 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924}
925
926static int __init
927init_cifs(void)
928{
929 int rc = 0;
930#ifdef CONFIG_PROC_FS
931 cifs_proc_init();
932#endif
Steve French2cd646a2006-09-28 19:43:08 +0000933/* INIT_LIST_HEAD(&GlobalServerList);*/ /* BB not implemented yet */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 INIT_LIST_HEAD(&GlobalSMBSessionList);
935 INIT_LIST_HEAD(&GlobalTreeConnectionList);
936 INIT_LIST_HEAD(&GlobalOplock_Q);
Steve French4ca9c192005-10-10 19:52:13 -0700937#ifdef CONFIG_CIFS_EXPERIMENTAL
938 INIT_LIST_HEAD(&GlobalDnotifyReqList);
939 INIT_LIST_HEAD(&GlobalDnotifyRsp_Q);
940#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941/*
942 * Initialize Global counters
943 */
944 atomic_set(&sesInfoAllocCount, 0);
945 atomic_set(&tconInfoAllocCount, 0);
946 atomic_set(&tcpSesAllocCount,0);
947 atomic_set(&tcpSesReconnectCount, 0);
948 atomic_set(&tconInfoReconnectCount, 0);
949
950 atomic_set(&bufAllocCount, 0);
Steve French4498eed52005-12-03 13:58:57 -0800951 atomic_set(&smBufAllocCount, 0);
952#ifdef CONFIG_CIFS_STATS2
953 atomic_set(&totBufAllocCount, 0);
954 atomic_set(&totSmBufAllocCount, 0);
955#endif /* CONFIG_CIFS_STATS2 */
956
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 atomic_set(&midCount, 0);
958 GlobalCurrentXid = 0;
959 GlobalTotalActiveXid = 0;
960 GlobalMaxActiveXid = 0;
Steve French2cd646a2006-09-28 19:43:08 +0000961 memset(Local_System_Name, 0, 15);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 rwlock_init(&GlobalSMBSeslock);
963 spin_lock_init(&GlobalMid_Lock);
964
965 if(cifs_max_pending < 2) {
966 cifs_max_pending = 2;
967 cFYI(1,("cifs_max_pending set to min of 2"));
968 } else if(cifs_max_pending > 256) {
969 cifs_max_pending = 256;
970 cFYI(1,("cifs_max_pending set to max of 256"));
971 }
972
973 rc = cifs_init_inodecache();
Steve French45af7a02006-04-21 22:52:25 +0000974 if (rc)
975 goto out_clean_proc;
976
977 rc = cifs_init_mids();
978 if (rc)
979 goto out_destroy_inodecache;
980
981 rc = cifs_init_request_bufs();
982 if (rc)
983 goto out_destroy_mids;
984
985 rc = register_filesystem(&cifs_fs_type);
986 if (rc)
987 goto out_destroy_request_bufs;
988
989 oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd");
990 if (IS_ERR(oplockThread)) {
991 rc = PTR_ERR(oplockThread);
992 cERROR(1,("error %d create oplock thread", rc));
993 goto out_unregister_filesystem;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 }
Steve French45af7a02006-04-21 22:52:25 +0000995
996 dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
997 if (IS_ERR(dnotifyThread)) {
998 rc = PTR_ERR(dnotifyThread);
999 cERROR(1,("error %d create dnotify thread", rc));
1000 goto out_stop_oplock_thread;
1001 }
1002
1003 return 0;
1004
1005 out_stop_oplock_thread:
1006 kthread_stop(oplockThread);
1007 out_unregister_filesystem:
1008 unregister_filesystem(&cifs_fs_type);
1009 out_destroy_request_bufs:
1010 cifs_destroy_request_bufs();
1011 out_destroy_mids:
1012 cifs_destroy_mids();
1013 out_destroy_inodecache:
1014 cifs_destroy_inodecache();
1015 out_clean_proc:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016#ifdef CONFIG_PROC_FS
1017 cifs_proc_clean();
1018#endif
1019 return rc;
1020}
1021
1022static void __exit
1023exit_cifs(void)
1024{
1025 cFYI(0, ("In unregister ie exit_cifs"));
1026#ifdef CONFIG_PROC_FS
1027 cifs_proc_clean();
1028#endif
1029 unregister_filesystem(&cifs_fs_type);
1030 cifs_destroy_inodecache();
1031 cifs_destroy_mids();
1032 cifs_destroy_request_bufs();
Steve French45af7a02006-04-21 22:52:25 +00001033 kthread_stop(oplockThread);
1034 kthread_stop(dnotifyThread);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035}
1036
1037MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
1038MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
1039MODULE_DESCRIPTION
1040 ("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows");
1041MODULE_VERSION(CIFS_VERSION);
1042module_init(init_cifs)
1043module_exit(exit_cifs)