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