VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / fs / cifs / cifsfs.c
1 /*
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
46 static struct quotactl_ops cifs_quotactl_ops;
47 #endif
48
49 int cifsFYI = 0;
50 int cifsERROR = 1;
51 int traceSMB = 0;
52 unsigned int oplockEnabled = 1;
53 unsigned int quotaEnabled = 0;
54 unsigned int linuxExtEnabled = 1;
55 unsigned int lookupCacheEnabled = 1;
56 unsigned int multiuser_mount = 0;
57 unsigned int extended_security = 0;
58 unsigned int ntlmv2_support = 0;
59 unsigned int sign_CIFS_PDUs = 1;
60 unsigned int CIFSMaximumBufferSize = CIFS_MAX_MSGSIZE;
61 struct task_struct * oplockThread = NULL;
62
63 extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
64                         const char *);
65 extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
66 void cifs_proc_init(void);
67 void cifs_proc_clean(void);
68
69 static DECLARE_COMPLETION(cifs_oplock_exited);
70
71
72 static int
73 cifs_read_super(struct super_block *sb, void *data,
74                 const char *devname, int silent)
75 {
76         struct inode *inode;
77         struct cifs_sb_info *cifs_sb;
78         int rc = 0;
79
80         sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
81         sb->s_fs_info = kmalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
82         cifs_sb = CIFS_SB(sb);
83         if(cifs_sb == NULL)
84                 return -ENOMEM;
85         else
86                 memset(cifs_sb,0,sizeof(struct cifs_sb_info));
87         
88
89         rc = cifs_mount(sb, cifs_sb, data, devname);
90
91         if (rc) {
92                 if (!silent)
93                         cERROR(1,
94                                ("cifs_mount failed w/return code = %d", rc));
95                 goto out_mount_failed;
96         }
97
98         sb->s_magic = CIFS_MAGIC_NUMBER;
99         sb->s_op = &cifs_super_ops;
100 /*      if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
101             sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
102 #ifdef CONFIG_CIFS_QUOTA
103         sb->s_qcop = &cifs_quotactl_ops;
104 #endif
105         sb->s_blocksize = CIFS_MAX_MSGSIZE;
106         sb->s_blocksize_bits = 14;      /* default 2**14 = CIFS_MAX_MSGSIZE */
107         inode = iget(sb, ROOT_I);
108
109         if (!inode) {
110                 rc = -ENOMEM;
111                 goto out_no_root;
112         }
113
114         sb->s_root = d_alloc_root(inode);
115
116         if (!sb->s_root) {
117                 rc = -ENOMEM;
118                 goto out_no_root;
119         }
120
121         return 0;
122
123 out_no_root:
124         cERROR(1, ("cifs_read_super: get root inode failed"));
125         if (inode)
126                 iput(inode);
127
128 out_mount_failed:
129         if(cifs_sb) {
130                 if(cifs_sb->local_nls)
131                         unload_nls(cifs_sb->local_nls); 
132                 kfree(cifs_sb);
133         }
134         return rc;
135 }
136
137 static void
138 cifs_put_super(struct super_block *sb)
139 {
140         int rc = 0;
141         struct cifs_sb_info *cifs_sb;
142
143         cFYI(1, ("In cifs_put_super"));
144         cifs_sb = CIFS_SB(sb);
145         if(cifs_sb == NULL) {
146                 cFYI(1,("Empty cifs superblock info passed to unmount"));
147                 return;
148         }
149         rc = cifs_umount(sb, cifs_sb); 
150         if (rc) {
151                 cERROR(1, ("cifs_umount failed with return code %d", rc));
152         }
153         unload_nls(cifs_sb->local_nls);
154         kfree(cifs_sb);
155         return;
156 }
157
158 static int
159 cifs_statfs(struct super_block *sb, struct kstatfs *buf)
160 {
161         int xid, rc;
162         struct cifs_sb_info *cifs_sb;
163         struct cifsTconInfo *pTcon;
164
165         xid = GetXid();
166
167         cifs_sb = CIFS_SB(sb);
168         pTcon = cifs_sb->tcon;
169
170         buf->f_type = CIFS_MAGIC_NUMBER;
171
172         /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */
173         buf->f_namelen = PATH_MAX;      /* PATH_MAX may be too long - it would presumably
174                                            be length of total path, note that some servers may be 
175                                            able to support more than this, but best to be safe
176                                            since Win2k and others can not handle very long filenames */
177         buf->f_files = 0;       /* undefined */
178         buf->f_ffree = 0;       /* unlimited */
179
180         rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls);
181
182         /*     
183            int f_type;
184            __fsid_t f_fsid;
185            int f_namelen;  */
186         /* BB get from info put in tcon struct at mount time with call to QFSAttrInfo */
187         FreeXid(xid);
188         return 0;               /* always return success? what if volume is no longer available? */
189 }
190
191 static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
192 {
193         struct cifs_sb_info *cifs_sb;
194
195         cifs_sb = CIFS_SB(inode->i_sb);
196
197         if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
198                 return 0;
199         } else /* file mode might have been restricted at mount time 
200                 on the client (above and beyond ACL on servers) for  
201                 servers which do not support setting and viewing mode bits,
202                 so allowing client to check permissions is useful */ 
203                 return vfs_permission(inode, mask);
204 }
205
206 static kmem_cache_t *cifs_inode_cachep;
207 static kmem_cache_t *cifs_req_cachep;
208 static kmem_cache_t *cifs_mid_cachep;
209 kmem_cache_t *cifs_oplock_cachep;
210 mempool_t *cifs_req_poolp;
211 mempool_t *cifs_mid_poolp;
212
213 static struct inode *
214 cifs_alloc_inode(struct super_block *sb)
215 {
216         struct cifsInodeInfo *cifs_inode;
217         cifs_inode =
218             (struct cifsInodeInfo *) kmem_cache_alloc(cifs_inode_cachep,
219                                                       SLAB_KERNEL);
220         if (!cifs_inode)
221                 return NULL;
222         cifs_inode->cifsAttrs = 0x20;   /* default */
223         atomic_set(&cifs_inode->inUse, 0);
224         cifs_inode->time = 0;
225         /* Until the file is open and we have gotten oplock
226         info back from the server, can not assume caching of
227         file data or metadata */
228         cifs_inode->clientCanCacheRead = FALSE;
229         cifs_inode->clientCanCacheAll = FALSE;
230         cifs_inode->vfs_inode.i_blksize = CIFS_MAX_MSGSIZE;
231         cifs_inode->vfs_inode.i_blkbits = 14;  /* 2**14 = CIFS_MAX_MSGSIZE */
232
233         INIT_LIST_HEAD(&cifs_inode->openFileList);
234         return &cifs_inode->vfs_inode;
235 }
236
237 static void
238 cifs_destroy_inode(struct inode *inode)
239 {
240         kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
241 }
242
243 /*
244  * cifs_show_options() is for displaying mount options in /proc/mounts.
245  * Not all settable options are displayed but most of the important
246  * ones are.
247  */
248 static int
249 cifs_show_options(struct seq_file *s, struct vfsmount *m)
250 {
251         struct cifs_sb_info *cifs_sb;
252
253         cifs_sb = CIFS_SB(m->mnt_sb);
254
255         if (cifs_sb) {
256                 if (cifs_sb->tcon) {
257                         seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
258                         if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->userName))
259                                 seq_printf(s, ",username=%s",
260                                            cifs_sb->tcon->ses->userName);
261                         if(cifs_sb->tcon->ses->domainName)
262                                 seq_printf(s, ",domain=%s",
263                                         cifs_sb->tcon->ses->domainName);
264                 }
265                 seq_printf(s, ",rsize=%d",cifs_sb->rsize);
266                 seq_printf(s, ",wsize=%d",cifs_sb->wsize);
267         }
268         return 0;
269 }
270
271 #ifdef CONFIG_CIFS_QUOTA
272 int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
273                 struct fs_disk_quota * pdquota)
274 {
275         int xid;
276         int rc = 0;
277         struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
278         struct cifsTconInfo *pTcon;
279         
280         if(cifs_sb)
281                 pTcon = cifs_sb->tcon;
282         else
283                 return -EIO;
284
285
286         xid = GetXid();
287         if(pTcon) {
288                 cFYI(1,("set type: 0x%x id: %d",quota_type,qid));               
289         } else {
290                 return -EIO;
291         }
292
293         FreeXid(xid);
294         return rc;
295 }
296
297 int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
298                 struct fs_disk_quota * pdquota)
299 {
300         int xid;
301         int rc = 0;
302         struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
303         struct cifsTconInfo *pTcon;
304
305         if(cifs_sb)
306                 pTcon = cifs_sb->tcon;
307         else
308                 return -EIO;
309
310         xid = GetXid();
311         if(pTcon) {
312                 cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
313         } else {
314                 rc = -EIO;
315         }
316
317         FreeXid(xid);
318         return rc;
319 }
320
321 int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
322 {
323         int xid; 
324         int rc = 0;
325         struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
326         struct cifsTconInfo *pTcon;
327
328         if(cifs_sb)
329                 pTcon = cifs_sb->tcon;
330         else
331                 return -EIO;
332
333         xid = GetXid();
334         if(pTcon) {
335                 cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation));
336         } else {
337                 rc = -EIO;
338         }
339
340         FreeXid(xid);
341         return rc;
342 }
343
344 int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats)
345 {
346         int xid;
347         int rc = 0;
348         struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
349         struct cifsTconInfo *pTcon;
350
351         if(cifs_sb) {
352                 pTcon = cifs_sb->tcon;
353         } else {
354                 return -EIO;
355         }
356         xid = GetXid();
357         if(pTcon) {
358                 cFYI(1,("pqstats %p",qstats));          
359         } else {
360                 rc = -EIO;
361         }
362
363         FreeXid(xid);
364         return rc;
365 }
366
367 static struct quotactl_ops cifs_quotactl_ops = {
368         .set_xquota     = cifs_xquota_set,
369         .get_xquota     = cifs_xquota_set,
370         .set_xstate     = cifs_xstate_set,
371         .get_xstate     = cifs_xstate_get,
372 };
373 #endif
374
375 static int cifs_remount(struct super_block *sb, int *flags, char *data)
376 {
377         *flags |= MS_NODIRATIME;
378         return 0;
379 }
380
381 struct super_operations cifs_super_ops = {
382         .read_inode = cifs_read_inode,
383         .put_super = cifs_put_super,
384         .statfs = cifs_statfs,
385         .alloc_inode = cifs_alloc_inode,
386         .destroy_inode = cifs_destroy_inode,
387 /*      .drop_inode         = generic_delete_inode, 
388         .delete_inode   = cifs_delete_inode,  *//* Do not need the above two functions     
389    unless later we add lazy close of inodes or unless the kernel forgets to call
390    us with the same number of releases (closes) as opens */
391         .show_options = cifs_show_options,
392 /*    .umount_begin   = cifs_umount_begin, *//* consider adding in the future */
393         .remount_fs = cifs_remount,
394 };
395
396 static struct super_block *
397 cifs_get_sb(struct file_system_type *fs_type,
398             int flags, const char *dev_name, void *data)
399 {
400         int rc;
401         struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
402
403         cFYI(1, ("Devname: %s flags: %d ", dev_name, flags));
404
405         if (IS_ERR(sb))
406                 return sb;
407
408         sb->s_flags = flags;
409
410         rc = cifs_read_super(sb, data, dev_name, flags & MS_VERBOSE ? 1 : 0);
411         if (rc) {
412                 up_write(&sb->s_umount);
413                 deactivate_super(sb);
414                 return ERR_PTR(rc);
415         }
416         sb->s_flags |= MS_ACTIVE;
417         return sb;
418 }
419
420 static ssize_t
421 cifs_read_wrapper(struct file * file, char __user *read_data, size_t read_size,
422           loff_t * poffset)
423 {
424         if(file == NULL)
425                 return -EIO;
426         else if(file->f_dentry == NULL)
427                 return -EIO;
428         else if(file->f_dentry->d_inode == NULL)
429                 return -EIO;
430
431         cFYI(1,("In read_wrapper size %zd at %lld",read_size,*poffset));
432         if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) {
433                 return generic_file_read(file,read_data,read_size,poffset);
434         } else {
435                 /* BB do we need to lock inode from here until after invalidate? */
436 /*              if(file->f_dentry->d_inode->i_mapping) {
437                         filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
438                         filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
439                 }*/
440 /*              cifs_revalidate(file->f_dentry);*/ /* BB fixme */
441
442                 /* BB we should make timer configurable - perhaps 
443                    by simply calling cifs_revalidate here */
444                 /* invalidate_remote_inode(file->f_dentry->d_inode);*/
445                 return generic_file_read(file,read_data,read_size,poffset);
446         }
447 }
448
449 static ssize_t
450 cifs_write_wrapper(struct file * file, const char __user *write_data,
451            size_t write_size, loff_t * poffset) 
452 {
453         ssize_t written;
454
455         if(file == NULL)
456                 return -EIO;
457         else if(file->f_dentry == NULL)
458                 return -EIO;
459         else if(file->f_dentry->d_inode == NULL)
460                 return -EIO;
461
462         cFYI(1,("In write_wrapper size %zd at %lld",write_size,*poffset));
463
464         /* check whether we can cache writes locally */
465         written = generic_file_write(file,write_data,write_size,poffset);
466         if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll)  {
467                 if(file->f_dentry->d_inode->i_mapping) {
468                         filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
469                 }
470         }
471         return written;
472 }
473
474
475 static struct file_system_type cifs_fs_type = {
476         .owner = THIS_MODULE,
477         .name = "cifs",
478         .get_sb = cifs_get_sb,
479         .kill_sb = kill_anon_super,
480         /*  .fs_flags */
481 };
482 struct inode_operations cifs_dir_inode_ops = {
483         .create = cifs_create,
484         .lookup = cifs_lookup,
485         .getattr = cifs_getattr,
486         .unlink = cifs_unlink,
487         .link = cifs_hardlink,
488         .mkdir = cifs_mkdir,
489         .rmdir = cifs_rmdir,
490         .rename = cifs_rename,
491         .permission = cifs_permission,
492 /*      revalidate:cifs_revalidate,   */
493         .setattr = cifs_setattr,
494         .symlink = cifs_symlink,
495         .mknod   = cifs_mknod,
496 };
497
498 struct inode_operations cifs_file_inode_ops = {
499 /*      revalidate:cifs_revalidate, */
500         .setattr = cifs_setattr,
501         .getattr = cifs_getattr, /* do we need this anymore? */
502         .rename = cifs_rename,
503         .permission = cifs_permission,
504 #ifdef CONFIG_CIFS_XATTR
505         .setxattr = cifs_setxattr,
506         .getxattr = cifs_getxattr,
507         .listxattr = cifs_listxattr,
508         .removexattr = cifs_removexattr,
509 #endif 
510 };
511
512 struct inode_operations cifs_symlink_inode_ops = {
513         .readlink = cifs_readlink,
514         .follow_link = cifs_follow_link,
515         .permission = cifs_permission,
516         /* BB add the following two eventually */
517         /* revalidate: cifs_revalidate,
518            setattr:    cifs_notify_change, *//* BB do we need notify change */
519 #ifdef CONFIG_CIFS_XATTR
520         .setxattr = cifs_setxattr,
521         .getxattr = cifs_getxattr,
522         .listxattr = cifs_listxattr,
523         .removexattr = cifs_removexattr,
524 #endif 
525 };
526
527 struct file_operations cifs_file_ops = {
528         .read = cifs_read_wrapper,
529         .write = cifs_write_wrapper, 
530         .open = cifs_open,
531         .release = cifs_close,
532         .lock = cifs_lock,
533         .fsync = cifs_fsync,
534         .flush = cifs_flush,
535         .mmap  = cifs_file_mmap,
536         .sendfile = generic_file_sendfile,
537         .dir_notify = cifs_dir_notify,
538 };
539
540 struct file_operations cifs_dir_ops = {
541         .readdir = cifs_readdir,
542         .release = cifs_closedir,
543         .read    = generic_read_dir,
544         .dir_notify = cifs_dir_notify,
545 };
546
547 static void
548 cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags)
549 {
550         struct cifsInodeInfo *cifsi = (struct cifsInodeInfo *) inode;
551
552         if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
553             SLAB_CTOR_CONSTRUCTOR) {
554                 inode_init_once(&cifsi->vfs_inode);
555                 INIT_LIST_HEAD(&cifsi->lockList);
556         }
557 }
558
559 static int
560 cifs_init_inodecache(void)
561 {
562         cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
563                                               sizeof (struct cifsInodeInfo),
564                                               0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
565                                               cifs_init_once, NULL);
566         if (cifs_inode_cachep == NULL)
567                 return -ENOMEM;
568
569         return 0;
570 }
571
572 static void
573 cifs_destroy_inodecache(void)
574 {
575         if (kmem_cache_destroy(cifs_inode_cachep))
576                 printk(KERN_WARNING "cifs_inode_cache: error freeing\n");
577 }
578
579 static int
580 cifs_init_request_bufs(void)
581 {
582         cifs_req_cachep = kmem_cache_create("cifs_request",
583                                             CIFS_MAX_MSGSIZE +
584                                             MAX_CIFS_HDR_SIZE, 0,
585                                             SLAB_HWCACHE_ALIGN, NULL, NULL);
586         if (cifs_req_cachep == NULL)
587                 return -ENOMEM;
588
589         cifs_req_poolp = mempool_create(CIFS_MIN_RCV_POOL,
590                                         mempool_alloc_slab,
591                                         mempool_free_slab,
592                                         cifs_req_cachep);
593
594         if(cifs_req_poolp == NULL) {
595                 kmem_cache_destroy(cifs_req_cachep);
596                 return -ENOMEM;
597         }
598
599         return 0;
600 }
601
602 static void
603 cifs_destroy_request_bufs(void)
604 {
605         mempool_destroy(cifs_req_poolp);
606         if (kmem_cache_destroy(cifs_req_cachep))
607                 printk(KERN_WARNING
608                        "cifs_destroy_request_cache: error not all structures were freed\n");
609 }
610
611 static int
612 cifs_init_mids(void)
613 {
614         cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
615                                 sizeof (struct mid_q_entry), 0,
616                                 SLAB_HWCACHE_ALIGN, NULL, NULL);
617         if (cifs_mid_cachep == NULL)
618                 return -ENOMEM;
619
620         cifs_mid_poolp = mempool_create(3 /* a reasonable min simultan opers */,
621                                         mempool_alloc_slab,
622                                         mempool_free_slab,
623                                         cifs_mid_cachep);
624         if(cifs_mid_poolp == NULL) {
625                 kmem_cache_destroy(cifs_mid_cachep);
626                 return -ENOMEM;
627         }
628
629         cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs",
630                                 sizeof (struct oplock_q_entry), 0,
631                                 SLAB_HWCACHE_ALIGN, NULL, NULL);
632         if (cifs_oplock_cachep == NULL) {
633                 kmem_cache_destroy(cifs_mid_cachep);
634                 mempool_destroy(cifs_mid_poolp);
635                 return -ENOMEM;
636         }
637
638         return 0;
639 }
640
641 static void
642 cifs_destroy_mids(void)
643 {
644         mempool_destroy(cifs_mid_poolp);
645         if (kmem_cache_destroy(cifs_mid_cachep))
646                 printk(KERN_WARNING
647                        "cifs_destroy_mids: error not all structures were freed\n");
648
649         if (kmem_cache_destroy(cifs_oplock_cachep))
650                 printk(KERN_WARNING
651                        "error not all oplock structures were freed\n");
652 }
653
654 static int cifs_oplock_thread(void * dummyarg)
655 {
656         struct oplock_q_entry * oplock_item;
657         struct cifsTconInfo *pTcon;
658         struct inode * inode;
659         __u16  netfid;
660         int rc;
661
662         daemonize("cifsoplockd");
663         allow_signal(SIGTERM);
664
665         oplockThread = current;
666         do {
667                 set_current_state(TASK_INTERRUPTIBLE);
668                 
669                 schedule_timeout(1*HZ);  
670                 spin_lock(&GlobalMid_Lock);
671                 if(list_empty(&GlobalOplock_Q)) {
672                         spin_unlock(&GlobalMid_Lock);
673                         set_current_state(TASK_INTERRUPTIBLE);
674                         schedule_timeout(39*HZ);
675                 } else {
676                         oplock_item = list_entry(GlobalOplock_Q.next, 
677                                 struct oplock_q_entry, qhead);
678                         if(oplock_item) {
679                                 cFYI(1,("found oplock item to write out")); 
680                                 pTcon = oplock_item->tcon;
681                                 inode = oplock_item->pinode;
682                                 netfid = oplock_item->netfid;
683                                 spin_unlock(&GlobalMid_Lock);
684                                 DeleteOplockQEntry(oplock_item);
685                                 /* can not grab inode sem here since it would
686                                 deadlock when oplock received on delete 
687                                 since vfs_unlink holds the i_sem across
688                                 the call */
689                                 /* down(&inode->i_sem);*/
690                                 if (S_ISREG(inode->i_mode)) {
691                                         rc = filemap_fdatawrite(inode->i_mapping);
692                                         if(CIFS_I(inode)->clientCanCacheRead == 0) {
693                                                 filemap_fdatawait(inode->i_mapping);
694                                                 invalidate_remote_inode(inode);
695                                         }
696                                 } else
697                                         rc = 0;
698                                 /* up(&inode->i_sem);*/
699                                 if (rc)
700                                         CIFS_I(inode)->write_behind_rc = rc;
701                                 cFYI(1,("Oplock flush inode %p rc %d",inode,rc));
702
703                                 /* releasing a stale oplock after recent reconnection 
704                                 of smb session using a now incorrect file 
705                                 handle is not a data integrity issue but do  
706                                 not bother sending an oplock release if session 
707                                 to server still is disconnected since oplock 
708                                 already released by the server in that case */
709                                 if(pTcon->tidStatus != CifsNeedReconnect) {
710                                     rc = CIFSSMBLock(0, pTcon, netfid,
711                                             0 /* len */ , 0 /* offset */, 0, 
712                                             0, LOCKING_ANDX_OPLOCK_RELEASE,
713                                             0 /* wait flag */);
714                                         cFYI(1,("Oplock release rc = %d ",rc));
715                                 }
716                         } else
717                                 spin_unlock(&GlobalMid_Lock);
718                 }
719         } while(!signal_pending(current));
720         complete_and_exit (&cifs_oplock_exited, 0);
721 }
722
723 static int __init
724 init_cifs(void)
725 {
726         int rc = 0;
727 #ifdef CONFIG_PROC_FS
728         cifs_proc_init();
729 #endif
730         INIT_LIST_HEAD(&GlobalServerList);      /* BB not implemented yet */
731         INIT_LIST_HEAD(&GlobalSMBSessionList);
732         INIT_LIST_HEAD(&GlobalTreeConnectionList);
733         INIT_LIST_HEAD(&GlobalOplock_Q);
734 /*
735  *  Initialize Global counters
736  */
737         atomic_set(&sesInfoAllocCount, 0);
738         atomic_set(&tconInfoAllocCount, 0);
739         atomic_set(&tcpSesAllocCount,0);
740         atomic_set(&tcpSesReconnectCount, 0);
741         atomic_set(&tconInfoReconnectCount, 0);
742
743         atomic_set(&bufAllocCount, 0);
744         atomic_set(&midCount, 0);
745         GlobalCurrentXid = 0;
746         GlobalTotalActiveXid = 0;
747         GlobalMaxActiveXid = 0;
748         GlobalSMBSeslock = RW_LOCK_UNLOCKED;
749         GlobalMid_Lock = SPIN_LOCK_UNLOCKED;
750
751         rc = cifs_init_inodecache();
752         if (!rc) {
753                 rc = cifs_init_mids();
754                 if (!rc) {
755                         rc = cifs_init_request_bufs();
756                         if (!rc) {
757                                 rc = register_filesystem(&cifs_fs_type);
758                                 if (!rc) {                
759                                         kernel_thread(cifs_oplock_thread, NULL, 
760                                                 CLONE_FS | CLONE_FILES | CLONE_VM);
761                                         return rc; /* Success */
762                                 } else
763                                         cifs_destroy_request_bufs();
764                         }
765                         cifs_destroy_mids();
766                 }
767                 cifs_destroy_inodecache();
768         }
769 #ifdef CONFIG_PROC_FS
770         cifs_proc_clean();
771 #endif
772         return rc;
773 }
774
775 static void __exit
776 exit_cifs(void)
777 {
778         cFYI(0, ("In unregister ie exit_cifs"));
779 #ifdef CONFIG_PROC_FS
780         cifs_proc_clean();
781 #endif
782         unregister_filesystem(&cifs_fs_type);
783         cifs_destroy_inodecache();
784         cifs_destroy_mids();
785         cifs_destroy_request_bufs();
786         if(oplockThread) {
787                 send_sig(SIGTERM, oplockThread, 1);
788                 wait_for_completion(&cifs_oplock_exited);
789         }
790 }
791
792 MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
793 MODULE_LICENSE("GPL");          /* combination of LGPL + GPL source behaves as GPL */
794 MODULE_DESCRIPTION
795     ("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows");
796 MODULE_VERSION(CIFS_VERSION);
797 module_init(init_cifs)
798 module_exit(exit_cifs)