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