blob: 1ebf7dafc1d757128e4084d6a1794485399b7ecc [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>
35#include "cifsfs.h"
36#include "cifspdu.h"
37#define DECLARE_GLOBALS_HERE
38#include "cifsglob.h"
39#include "cifsproto.h"
40#include "cifs_debug.h"
41#include "cifs_fs_sb.h"
42#include <linux/mm.h>
43#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
44
45#ifdef CONFIG_CIFS_QUOTA
46static struct quotactl_ops cifs_quotactl_ops;
47#endif
48
49int cifsFYI = 0;
50int cifsERROR = 1;
51int traceSMB = 0;
52unsigned int oplockEnabled = 1;
53unsigned int experimEnabled = 0;
54unsigned int linuxExtEnabled = 1;
55unsigned int lookupCacheEnabled = 1;
56unsigned int multiuser_mount = 0;
57unsigned int extended_security = 0;
58unsigned int ntlmv2_support = 0;
59unsigned int sign_CIFS_PDUs = 1;
60extern struct task_struct * oplockThread; /* remove sparse warning */
61struct task_struct * oplockThread = NULL;
62unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
63module_param(CIFSMaxBufSize, int, 0);
64MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048");
65unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
66module_param(cifs_min_rcv, int, 0);
67MODULE_PARM_DESC(cifs_min_rcv,"Network buffers in pool. Default: 4 Range: 1 to 64");
68unsigned int cifs_min_small = 30;
69module_param(cifs_min_small, int, 0);
70MODULE_PARM_DESC(cifs_min_small,"Small network buffers in pool. Default: 30 Range: 2 to 256");
71unsigned int cifs_max_pending = CIFS_MAX_REQ;
72module_param(cifs_max_pending, int, 0);
73MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256");
74
75static DECLARE_COMPLETION(cifs_oplock_exited);
76
77extern mempool_t *cifs_sm_req_poolp;
78extern mempool_t *cifs_req_poolp;
79extern mempool_t *cifs_mid_poolp;
80
81extern kmem_cache_t *cifs_oplock_cachep;
82
83static int
84cifs_read_super(struct super_block *sb, void *data,
85 const char *devname, int silent)
86{
87 struct inode *inode;
88 struct cifs_sb_info *cifs_sb;
89 int rc = 0;
90
91 sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
92 sb->s_fs_info = kmalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
93 cifs_sb = CIFS_SB(sb);
94 if(cifs_sb == NULL)
95 return -ENOMEM;
96 else
97 memset(cifs_sb,0,sizeof(struct cifs_sb_info));
98
99
100 rc = cifs_mount(sb, cifs_sb, data, devname);
101
102 if (rc) {
103 if (!silent)
104 cERROR(1,
105 ("cifs_mount failed w/return code = %d", rc));
106 goto out_mount_failed;
107 }
108
109 sb->s_magic = CIFS_MAGIC_NUMBER;
110 sb->s_op = &cifs_super_ops;
111/* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
112 sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
113#ifdef CONFIG_CIFS_QUOTA
114 sb->s_qcop = &cifs_quotactl_ops;
115#endif
116 sb->s_blocksize = CIFS_MAX_MSGSIZE;
117 sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
118 inode = iget(sb, ROOT_I);
119
120 if (!inode) {
121 rc = -ENOMEM;
122 goto out_no_root;
123 }
124
125 sb->s_root = d_alloc_root(inode);
126
127 if (!sb->s_root) {
128 rc = -ENOMEM;
129 goto out_no_root;
130 }
131
132 return 0;
133
134out_no_root:
135 cERROR(1, ("cifs_read_super: get root inode failed"));
136 if (inode)
137 iput(inode);
138
139out_mount_failed:
140 if(cifs_sb) {
141 if(cifs_sb->local_nls)
142 unload_nls(cifs_sb->local_nls);
143 kfree(cifs_sb);
144 }
145 return rc;
146}
147
148static void
149cifs_put_super(struct super_block *sb)
150{
151 int rc = 0;
152 struct cifs_sb_info *cifs_sb;
153
154 cFYI(1, ("In cifs_put_super"));
155 cifs_sb = CIFS_SB(sb);
156 if(cifs_sb == NULL) {
157 cFYI(1,("Empty cifs superblock info passed to unmount"));
158 return;
159 }
160 rc = cifs_umount(sb, cifs_sb);
161 if (rc) {
162 cERROR(1, ("cifs_umount failed with return code %d", rc));
163 }
164 unload_nls(cifs_sb->local_nls);
165 kfree(cifs_sb);
166 return;
167}
168
169static int
170cifs_statfs(struct super_block *sb, struct kstatfs *buf)
171{
Steve Frenchc81156d2005-04-28 22:41:07 -0700172 int xid;
173 int rc = -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 struct cifs_sb_info *cifs_sb;
175 struct cifsTconInfo *pTcon;
176
177 xid = GetXid();
178
179 cifs_sb = CIFS_SB(sb);
180 pTcon = cifs_sb->tcon;
181
182 buf->f_type = CIFS_MAGIC_NUMBER;
183
184 /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */
Steve Frenchc81156d2005-04-28 22:41:07 -0700185 buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would
186 presumably be total path, but note
187 that some servers (includinng Samba 3)
188 have a shorter maximum path */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 buf->f_files = 0; /* undefined */
190 buf->f_ffree = 0; /* unlimited */
191
192#ifdef CONFIG_CIFS_EXPERIMENTAL
193/* BB we could add a second check for a QFS Unix capability bit */
Steve Frenchf28ac912005-04-28 22:41:07 -0700194/* BB FIXME check CIFS_POSIX_EXTENSIONS Unix cap first FIXME BB */
Steve Frenchc81156d2005-04-28 22:41:07 -0700195 if ((pTcon->ses->capabilities & CAP_UNIX) && (CIFS_POSIX_EXTENSIONS &
196 le64_to_cpu(pTcon->fsUnixInfo.Capability)))
Steve French737b7582005-04-28 22:41:06 -0700197 rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198
199 /* Only need to call the old QFSInfo if failed
200 on newer one */
201 if(rc)
202#endif /* CIFS_EXPERIMENTAL */
Steve French737b7582005-04-28 22:41:06 -0700203 rc = CIFSSMBQFSInfo(xid, pTcon, buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204
205 /*
206 int f_type;
207 __fsid_t f_fsid;
208 int f_namelen; */
Steve Frenchc81156d2005-04-28 22:41:07 -0700209 /* BB get from info in tcon struct at mount time call to QFSAttrInfo */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 FreeXid(xid);
Steve Frenchc81156d2005-04-28 22:41:07 -0700211 return 0; /* always return success? what if volume is no
212 longer available? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213}
214
215static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
216{
217 struct cifs_sb_info *cifs_sb;
218
219 cifs_sb = CIFS_SB(inode->i_sb);
220
221 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
222 return 0;
223 } else /* file mode might have been restricted at mount time
224 on the client (above and beyond ACL on servers) for
225 servers which do not support setting and viewing mode bits,
226 so allowing client to check permissions is useful */
227 return generic_permission(inode, mask, NULL);
228}
229
230static kmem_cache_t *cifs_inode_cachep;
231static kmem_cache_t *cifs_req_cachep;
232static kmem_cache_t *cifs_mid_cachep;
233kmem_cache_t *cifs_oplock_cachep;
234static kmem_cache_t *cifs_sm_req_cachep;
235mempool_t *cifs_sm_req_poolp;
236mempool_t *cifs_req_poolp;
237mempool_t *cifs_mid_poolp;
238
239static struct inode *
240cifs_alloc_inode(struct super_block *sb)
241{
242 struct cifsInodeInfo *cifs_inode;
243 cifs_inode = kmem_cache_alloc(cifs_inode_cachep, SLAB_KERNEL);
244 if (!cifs_inode)
245 return NULL;
246 cifs_inode->cifsAttrs = 0x20; /* default */
247 atomic_set(&cifs_inode->inUse, 0);
248 cifs_inode->time = 0;
249 /* Until the file is open and we have gotten oplock
250 info back from the server, can not assume caching of
251 file data or metadata */
252 cifs_inode->clientCanCacheRead = FALSE;
253 cifs_inode->clientCanCacheAll = FALSE;
254 cifs_inode->vfs_inode.i_blksize = CIFS_MAX_MSGSIZE;
255 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
256
257 INIT_LIST_HEAD(&cifs_inode->openFileList);
258 return &cifs_inode->vfs_inode;
259}
260
261static void
262cifs_destroy_inode(struct inode *inode)
263{
264 kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
265}
266
267/*
268 * cifs_show_options() is for displaying mount options in /proc/mounts.
269 * Not all settable options are displayed but most of the important
270 * ones are.
271 */
272static int
273cifs_show_options(struct seq_file *s, struct vfsmount *m)
274{
275 struct cifs_sb_info *cifs_sb;
276
277 cifs_sb = CIFS_SB(m->mnt_sb);
278
279 if (cifs_sb) {
280 if (cifs_sb->tcon) {
281 seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
282 if (cifs_sb->tcon->ses) {
283 if (cifs_sb->tcon->ses->userName)
284 seq_printf(s, ",username=%s",
285 cifs_sb->tcon->ses->userName);
286 if(cifs_sb->tcon->ses->domainName)
287 seq_printf(s, ",domain=%s",
288 cifs_sb->tcon->ses->domainName);
289 }
290 }
291 seq_printf(s, ",rsize=%d",cifs_sb->rsize);
292 seq_printf(s, ",wsize=%d",cifs_sb->wsize);
293 }
294 return 0;
295}
296
297#ifdef CONFIG_CIFS_QUOTA
298int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
299 struct fs_disk_quota * pdquota)
300{
301 int xid;
302 int rc = 0;
303 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
304 struct cifsTconInfo *pTcon;
305
306 if(cifs_sb)
307 pTcon = cifs_sb->tcon;
308 else
309 return -EIO;
310
311
312 xid = GetXid();
313 if(pTcon) {
314 cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
315 } else {
316 return -EIO;
317 }
318
319 FreeXid(xid);
320 return rc;
321}
322
323int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
324 struct fs_disk_quota * pdquota)
325{
326 int xid;
327 int rc = 0;
328 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
329 struct cifsTconInfo *pTcon;
330
331 if(cifs_sb)
332 pTcon = cifs_sb->tcon;
333 else
334 return -EIO;
335
336 xid = GetXid();
337 if(pTcon) {
338 cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
339 } else {
340 rc = -EIO;
341 }
342
343 FreeXid(xid);
344 return rc;
345}
346
347int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
348{
349 int xid;
350 int rc = 0;
351 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
352 struct cifsTconInfo *pTcon;
353
354 if(cifs_sb)
355 pTcon = cifs_sb->tcon;
356 else
357 return -EIO;
358
359 xid = GetXid();
360 if(pTcon) {
361 cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation));
362 } else {
363 rc = -EIO;
364 }
365
366 FreeXid(xid);
367 return rc;
368}
369
370int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats)
371{
372 int xid;
373 int rc = 0;
374 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
375 struct cifsTconInfo *pTcon;
376
377 if(cifs_sb) {
378 pTcon = cifs_sb->tcon;
379 } else {
380 return -EIO;
381 }
382 xid = GetXid();
383 if(pTcon) {
384 cFYI(1,("pqstats %p",qstats));
385 } else {
386 rc = -EIO;
387 }
388
389 FreeXid(xid);
390 return rc;
391}
392
393static struct quotactl_ops cifs_quotactl_ops = {
394 .set_xquota = cifs_xquota_set,
395 .get_xquota = cifs_xquota_set,
396 .set_xstate = cifs_xstate_set,
397 .get_xstate = cifs_xstate_get,
398};
399#endif
400
401static int cifs_remount(struct super_block *sb, int *flags, char *data)
402{
403 *flags |= MS_NODIRATIME;
404 return 0;
405}
406
407struct super_operations cifs_super_ops = {
408 .read_inode = cifs_read_inode,
409 .put_super = cifs_put_super,
410 .statfs = cifs_statfs,
411 .alloc_inode = cifs_alloc_inode,
412 .destroy_inode = cifs_destroy_inode,
413/* .drop_inode = generic_delete_inode,
414 .delete_inode = cifs_delete_inode, *//* Do not need the above two functions
415 unless later we add lazy close of inodes or unless the kernel forgets to call
416 us with the same number of releases (closes) as opens */
417 .show_options = cifs_show_options,
418/* .umount_begin = cifs_umount_begin, *//* consider adding in the future */
419 .remount_fs = cifs_remount,
420};
421
422static struct super_block *
423cifs_get_sb(struct file_system_type *fs_type,
424 int flags, const char *dev_name, void *data)
425{
426 int rc;
427 struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
428
429 cFYI(1, ("Devname: %s flags: %d ", dev_name, flags));
430
431 if (IS_ERR(sb))
432 return sb;
433
434 sb->s_flags = flags;
435
436 rc = cifs_read_super(sb, data, dev_name, flags & MS_VERBOSE ? 1 : 0);
437 if (rc) {
438 up_write(&sb->s_umount);
439 deactivate_super(sb);
440 return ERR_PTR(rc);
441 }
442 sb->s_flags |= MS_ACTIVE;
443 return sb;
444}
445
446static ssize_t
447cifs_read_wrapper(struct file * file, char __user *read_data, size_t read_size,
448 loff_t * poffset)
449{
450 if(file->f_dentry == NULL)
451 return -EIO;
452 else if(file->f_dentry->d_inode == NULL)
453 return -EIO;
454
455 cFYI(1,("In read_wrapper size %zd at %lld",read_size,*poffset));
456
457 if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) {
458 return generic_file_read(file,read_data,read_size,poffset);
459 } else {
460 /* BB do we need to lock inode from here until after invalidate? */
461/* if(file->f_dentry->d_inode->i_mapping) {
462 filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
463 filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
464 }*/
465/* cifs_revalidate(file->f_dentry);*/ /* BB fixme */
466
467 /* BB we should make timer configurable - perhaps
468 by simply calling cifs_revalidate here */
469 /* invalidate_remote_inode(file->f_dentry->d_inode);*/
470 return generic_file_read(file,read_data,read_size,poffset);
471 }
472}
473
474static ssize_t
475cifs_write_wrapper(struct file * file, const char __user *write_data,
476 size_t write_size, loff_t * poffset)
477{
478 ssize_t written;
479
480 if(file->f_dentry == NULL)
481 return -EIO;
482 else if(file->f_dentry->d_inode == NULL)
483 return -EIO;
484
485 cFYI(1,("In write_wrapper size %zd at %lld",write_size,*poffset));
486
487 written = generic_file_write(file,write_data,write_size,poffset);
488 if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll) {
489 if(file->f_dentry->d_inode->i_mapping) {
490 filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
491 }
492 }
493 return written;
494}
495
496
497static struct file_system_type cifs_fs_type = {
498 .owner = THIS_MODULE,
499 .name = "cifs",
500 .get_sb = cifs_get_sb,
501 .kill_sb = kill_anon_super,
502 /* .fs_flags */
503};
504struct inode_operations cifs_dir_inode_ops = {
505 .create = cifs_create,
506 .lookup = cifs_lookup,
507 .getattr = cifs_getattr,
508 .unlink = cifs_unlink,
509 .link = cifs_hardlink,
510 .mkdir = cifs_mkdir,
511 .rmdir = cifs_rmdir,
512 .rename = cifs_rename,
513 .permission = cifs_permission,
514/* revalidate:cifs_revalidate, */
515 .setattr = cifs_setattr,
516 .symlink = cifs_symlink,
517 .mknod = cifs_mknod,
518#ifdef CONFIG_CIFS_XATTR
519 .setxattr = cifs_setxattr,
520 .getxattr = cifs_getxattr,
521 .listxattr = cifs_listxattr,
522 .removexattr = cifs_removexattr,
523#endif
524};
525
526struct inode_operations cifs_file_inode_ops = {
527/* revalidate:cifs_revalidate, */
528 .setattr = cifs_setattr,
529 .getattr = cifs_getattr, /* do we need this anymore? */
530 .rename = cifs_rename,
531 .permission = cifs_permission,
532#ifdef CONFIG_CIFS_XATTR
533 .setxattr = cifs_setxattr,
534 .getxattr = cifs_getxattr,
535 .listxattr = cifs_listxattr,
536 .removexattr = cifs_removexattr,
537#endif
538};
539
540struct inode_operations cifs_symlink_inode_ops = {
541 .readlink = generic_readlink,
542 .follow_link = cifs_follow_link,
543 .put_link = cifs_put_link,
544 .permission = cifs_permission,
545 /* BB add the following two eventually */
546 /* revalidate: cifs_revalidate,
547 setattr: cifs_notify_change, *//* BB do we need notify change */
548#ifdef CONFIG_CIFS_XATTR
549 .setxattr = cifs_setxattr,
550 .getxattr = cifs_getxattr,
551 .listxattr = cifs_listxattr,
552 .removexattr = cifs_removexattr,
553#endif
554};
555
556struct file_operations cifs_file_ops = {
557 .read = cifs_read_wrapper,
558 .write = cifs_write_wrapper,
559 .open = cifs_open,
560 .release = cifs_close,
561 .lock = cifs_lock,
562 .fsync = cifs_fsync,
563 .flush = cifs_flush,
564 .mmap = cifs_file_mmap,
565 .sendfile = generic_file_sendfile,
Steve Frenchc67593a2005-04-28 22:41:04 -0700566#ifdef CONFIG_CIFS_POSIX
567 .ioctl = cifs_ioctl,
568#endif /* CONFIG_CIFS_POSIX */
569
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570#ifdef CONFIG_CIFS_EXPERIMENTAL
571 .readv = generic_file_readv,
572 .writev = generic_file_writev,
573 .aio_read = generic_file_aio_read,
574 .aio_write = generic_file_aio_write,
575 .dir_notify = cifs_dir_notify,
576#endif /* CONFIG_CIFS_EXPERIMENTAL */
577};
578
579struct file_operations cifs_file_direct_ops = {
580 /* no mmap, no aio, no readv -
581 BB reevaluate whether they can be done with directio, no cache */
582 .read = cifs_user_read,
583 .write = cifs_user_write,
584 .open = cifs_open,
585 .release = cifs_close,
586 .lock = cifs_lock,
587 .fsync = cifs_fsync,
588 .flush = cifs_flush,
589 .sendfile = generic_file_sendfile, /* BB removeme BB */
Steve Frenchc67593a2005-04-28 22:41:04 -0700590#ifdef CONFIG_CIFS_POSIX
591 .ioctl = cifs_ioctl,
592#endif /* CONFIG_CIFS_POSIX */
593
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594#ifdef CONFIG_CIFS_EXPERIMENTAL
595 .dir_notify = cifs_dir_notify,
596#endif /* CONFIG_CIFS_EXPERIMENTAL */
597};
598
599struct file_operations cifs_dir_ops = {
600 .readdir = cifs_readdir,
601 .release = cifs_closedir,
602 .read = generic_read_dir,
603#ifdef CONFIG_CIFS_EXPERIMENTAL
604 .dir_notify = cifs_dir_notify,
605#endif /* CONFIG_CIFS_EXPERIMENTAL */
Steve Frenchf28ac912005-04-28 22:41:07 -0700606 .ioctl = cifs_ioctl,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607};
608
609static void
610cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags)
611{
612 struct cifsInodeInfo *cifsi = inode;
613
614 if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
615 SLAB_CTOR_CONSTRUCTOR) {
616 inode_init_once(&cifsi->vfs_inode);
617 INIT_LIST_HEAD(&cifsi->lockList);
618 }
619}
620
621static int
622cifs_init_inodecache(void)
623{
624 cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
625 sizeof (struct cifsInodeInfo),
626 0, SLAB_RECLAIM_ACCOUNT,
627 cifs_init_once, NULL);
628 if (cifs_inode_cachep == NULL)
629 return -ENOMEM;
630
631 return 0;
632}
633
634static void
635cifs_destroy_inodecache(void)
636{
637 if (kmem_cache_destroy(cifs_inode_cachep))
638 printk(KERN_WARNING "cifs_inode_cache: error freeing\n");
639}
640
641static int
642cifs_init_request_bufs(void)
643{
644 if(CIFSMaxBufSize < 8192) {
645 /* Buffer size can not be smaller than 2 * PATH_MAX since maximum
646 Unicode path name has to fit in any SMB/CIFS path based frames */
647 CIFSMaxBufSize = 8192;
648 } else if (CIFSMaxBufSize > 1024*127) {
649 CIFSMaxBufSize = 1024 * 127;
650 } else {
651 CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/
652 }
653/* cERROR(1,("CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize)); */
654 cifs_req_cachep = kmem_cache_create("cifs_request",
655 CIFSMaxBufSize +
656 MAX_CIFS_HDR_SIZE, 0,
657 SLAB_HWCACHE_ALIGN, NULL, NULL);
658 if (cifs_req_cachep == NULL)
659 return -ENOMEM;
660
661 if(cifs_min_rcv < 1)
662 cifs_min_rcv = 1;
663 else if (cifs_min_rcv > 64) {
664 cifs_min_rcv = 64;
665 cERROR(1,("cifs_min_rcv set to maximum (64)"));
666 }
667
668 cifs_req_poolp = mempool_create(cifs_min_rcv,
669 mempool_alloc_slab,
670 mempool_free_slab,
671 cifs_req_cachep);
672
673 if(cifs_req_poolp == NULL) {
674 kmem_cache_destroy(cifs_req_cachep);
675 return -ENOMEM;
676 }
677 /* 256 (MAX_CIFS_HDR_SIZE bytes is enough for most SMB responses and
678 almost all handle based requests (but not write response, nor is it
679 sufficient for path based requests). A smaller size would have
680 been more efficient (compacting multiple slab items on one 4k page)
681 for the case in which debug was on, but this larger size allows
682 more SMBs to use small buffer alloc and is still much more
683 efficient to alloc 1 per page off the slab compared to 17K (5page)
684 alloc of large cifs buffers even when page debugging is on */
685 cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq",
686 MAX_CIFS_HDR_SIZE, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
687 if (cifs_sm_req_cachep == NULL) {
688 mempool_destroy(cifs_req_poolp);
689 kmem_cache_destroy(cifs_req_cachep);
690 return -ENOMEM;
691 }
692
693 if(cifs_min_small < 2)
694 cifs_min_small = 2;
695 else if (cifs_min_small > 256) {
696 cifs_min_small = 256;
697 cFYI(1,("cifs_min_small set to maximum (256)"));
698 }
699
700 cifs_sm_req_poolp = mempool_create(cifs_min_small,
701 mempool_alloc_slab,
702 mempool_free_slab,
703 cifs_sm_req_cachep);
704
705 if(cifs_sm_req_poolp == NULL) {
706 mempool_destroy(cifs_req_poolp);
707 kmem_cache_destroy(cifs_req_cachep);
708 kmem_cache_destroy(cifs_sm_req_cachep);
709 return -ENOMEM;
710 }
711
712 return 0;
713}
714
715static void
716cifs_destroy_request_bufs(void)
717{
718 mempool_destroy(cifs_req_poolp);
719 if (kmem_cache_destroy(cifs_req_cachep))
720 printk(KERN_WARNING
721 "cifs_destroy_request_cache: error not all structures were freed\n");
722 mempool_destroy(cifs_sm_req_poolp);
723 if (kmem_cache_destroy(cifs_sm_req_cachep))
724 printk(KERN_WARNING
725 "cifs_destroy_request_cache: cifs_small_rq free error\n");
726}
727
728static int
729cifs_init_mids(void)
730{
731 cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
732 sizeof (struct mid_q_entry), 0,
733 SLAB_HWCACHE_ALIGN, NULL, NULL);
734 if (cifs_mid_cachep == NULL)
735 return -ENOMEM;
736
737 cifs_mid_poolp = mempool_create(3 /* a reasonable min simultan opers */,
738 mempool_alloc_slab,
739 mempool_free_slab,
740 cifs_mid_cachep);
741 if(cifs_mid_poolp == NULL) {
742 kmem_cache_destroy(cifs_mid_cachep);
743 return -ENOMEM;
744 }
745
746 cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs",
747 sizeof (struct oplock_q_entry), 0,
748 SLAB_HWCACHE_ALIGN, NULL, NULL);
749 if (cifs_oplock_cachep == NULL) {
750 kmem_cache_destroy(cifs_mid_cachep);
751 mempool_destroy(cifs_mid_poolp);
752 return -ENOMEM;
753 }
754
755 return 0;
756}
757
758static void
759cifs_destroy_mids(void)
760{
761 mempool_destroy(cifs_mid_poolp);
762 if (kmem_cache_destroy(cifs_mid_cachep))
763 printk(KERN_WARNING
764 "cifs_destroy_mids: error not all structures were freed\n");
765
766 if (kmem_cache_destroy(cifs_oplock_cachep))
767 printk(KERN_WARNING
768 "error not all oplock structures were freed\n");
769}
770
771static int cifs_oplock_thread(void * dummyarg)
772{
773 struct oplock_q_entry * oplock_item;
774 struct cifsTconInfo *pTcon;
775 struct inode * inode;
776 __u16 netfid;
777 int rc;
778
779 daemonize("cifsoplockd");
780 allow_signal(SIGTERM);
781
782 oplockThread = current;
783 do {
Steve Frenchede13272005-08-30 20:10:14 -0700784 if (try_to_freeze())
785 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 set_current_state(TASK_INTERRUPTIBLE);
787
788 schedule_timeout(1*HZ);
789 spin_lock(&GlobalMid_Lock);
790 if(list_empty(&GlobalOplock_Q)) {
791 spin_unlock(&GlobalMid_Lock);
792 set_current_state(TASK_INTERRUPTIBLE);
793 schedule_timeout(39*HZ);
794 } else {
795 oplock_item = list_entry(GlobalOplock_Q.next,
796 struct oplock_q_entry, qhead);
797 if(oplock_item) {
798 cFYI(1,("found oplock item to write out"));
799 pTcon = oplock_item->tcon;
800 inode = oplock_item->pinode;
801 netfid = oplock_item->netfid;
802 spin_unlock(&GlobalMid_Lock);
803 DeleteOplockQEntry(oplock_item);
804 /* can not grab inode sem here since it would
805 deadlock when oplock received on delete
806 since vfs_unlink holds the i_sem across
807 the call */
808 /* down(&inode->i_sem);*/
809 if (S_ISREG(inode->i_mode)) {
810 rc = filemap_fdatawrite(inode->i_mapping);
811 if(CIFS_I(inode)->clientCanCacheRead == 0) {
812 filemap_fdatawait(inode->i_mapping);
813 invalidate_remote_inode(inode);
814 }
815 } else
816 rc = 0;
817 /* up(&inode->i_sem);*/
818 if (rc)
819 CIFS_I(inode)->write_behind_rc = rc;
820 cFYI(1,("Oplock flush inode %p rc %d",inode,rc));
821
822 /* releasing a stale oplock after recent reconnection
823 of smb session using a now incorrect file
824 handle is not a data integrity issue but do
825 not bother sending an oplock release if session
826 to server still is disconnected since oplock
827 already released by the server in that case */
828 if(pTcon->tidStatus != CifsNeedReconnect) {
829 rc = CIFSSMBLock(0, pTcon, netfid,
830 0 /* len */ , 0 /* offset */, 0,
831 0, LOCKING_ANDX_OPLOCK_RELEASE,
832 0 /* wait flag */);
833 cFYI(1,("Oplock release rc = %d ",rc));
834 }
835 } else
836 spin_unlock(&GlobalMid_Lock);
837 }
838 } while(!signal_pending(current));
839 complete_and_exit (&cifs_oplock_exited, 0);
Steve French57337e42005-04-28 22:41:10 -0700840 oplockThread = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841}
842
843static int __init
844init_cifs(void)
845{
846 int rc = 0;
847#ifdef CONFIG_PROC_FS
848 cifs_proc_init();
849#endif
850 INIT_LIST_HEAD(&GlobalServerList); /* BB not implemented yet */
851 INIT_LIST_HEAD(&GlobalSMBSessionList);
852 INIT_LIST_HEAD(&GlobalTreeConnectionList);
853 INIT_LIST_HEAD(&GlobalOplock_Q);
854/*
855 * Initialize Global counters
856 */
857 atomic_set(&sesInfoAllocCount, 0);
858 atomic_set(&tconInfoAllocCount, 0);
859 atomic_set(&tcpSesAllocCount,0);
860 atomic_set(&tcpSesReconnectCount, 0);
861 atomic_set(&tconInfoReconnectCount, 0);
862
863 atomic_set(&bufAllocCount, 0);
864 atomic_set(&midCount, 0);
865 GlobalCurrentXid = 0;
866 GlobalTotalActiveXid = 0;
867 GlobalMaxActiveXid = 0;
868 rwlock_init(&GlobalSMBSeslock);
869 spin_lock_init(&GlobalMid_Lock);
870
871 if(cifs_max_pending < 2) {
872 cifs_max_pending = 2;
873 cFYI(1,("cifs_max_pending set to min of 2"));
874 } else if(cifs_max_pending > 256) {
875 cifs_max_pending = 256;
876 cFYI(1,("cifs_max_pending set to max of 256"));
877 }
878
879 rc = cifs_init_inodecache();
880 if (!rc) {
881 rc = cifs_init_mids();
882 if (!rc) {
883 rc = cifs_init_request_bufs();
884 if (!rc) {
885 rc = register_filesystem(&cifs_fs_type);
886 if (!rc) {
887 rc = (int)kernel_thread(cifs_oplock_thread, NULL,
888 CLONE_FS | CLONE_FILES | CLONE_VM);
889 if(rc > 0)
890 return 0;
891 else
892 cERROR(1,("error %d create oplock thread",rc));
893 }
894 cifs_destroy_request_bufs();
895 }
896 cifs_destroy_mids();
897 }
898 cifs_destroy_inodecache();
899 }
900#ifdef CONFIG_PROC_FS
901 cifs_proc_clean();
902#endif
903 return rc;
904}
905
906static void __exit
907exit_cifs(void)
908{
909 cFYI(0, ("In unregister ie exit_cifs"));
910#ifdef CONFIG_PROC_FS
911 cifs_proc_clean();
912#endif
913 unregister_filesystem(&cifs_fs_type);
914 cifs_destroy_inodecache();
915 cifs_destroy_mids();
916 cifs_destroy_request_bufs();
917 if(oplockThread) {
918 send_sig(SIGTERM, oplockThread, 1);
919 wait_for_completion(&cifs_oplock_exited);
920 }
921}
922
923MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
924MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */
925MODULE_DESCRIPTION
926 ("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows");
927MODULE_VERSION(CIFS_VERSION);
928module_init(init_cifs)
929module_exit(exit_cifs)