linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / fs / cifs / cifsfs.c
index 9373e22..79eeccd 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/vfs.h>
 #include <linux/mempool.h>
 #include <linux/delay.h>
-#include <linux/kthread.h>
 #include "cifsfs.h"
 #include "cifspdu.h"
 #define DECLARE_GLOBALS_HERE
@@ -56,8 +55,8 @@ unsigned int experimEnabled = 0;
 unsigned int linuxExtEnabled = 1;
 unsigned int lookupCacheEnabled = 1;
 unsigned int multiuser_mount = 0;
-unsigned int extended_security = CIFSSEC_DEF;
-/* unsigned int ntlmv2_support = 0; */
+unsigned int extended_security = 0;
+unsigned int ntlmv2_support = 0;
 unsigned int sign_CIFS_PDUs = 1;
 extern struct task_struct * oplockThread; /* remove sparse warning */
 struct task_struct * oplockThread = NULL;
@@ -76,6 +75,9 @@ unsigned int cifs_max_pending = CIFS_MAX_REQ;
 module_param(cifs_max_pending, int, 0);
 MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256");
 
+static DECLARE_COMPLETION(cifs_oplock_exited);
+static DECLARE_COMPLETION(cifs_dnotify_exited);
+
 extern mempool_t *cifs_sm_req_poolp;
 extern mempool_t *cifs_req_poolp;
 extern mempool_t *cifs_mid_poolp;
@@ -91,10 +93,13 @@ cifs_read_super(struct super_block *sb, void *data,
        int rc = 0;
 
        sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
-       sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
+       sb->s_fs_info = kmalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
        cifs_sb = CIFS_SB(sb);
        if(cifs_sb == NULL)
                return -ENOMEM;
+       else
+               memset(cifs_sb,0,sizeof(struct cifs_sb_info));
+       
 
        rc = cifs_mount(sb, cifs_sb, data, devname);
 
@@ -166,9 +171,8 @@ cifs_put_super(struct super_block *sb)
 }
 
 static int
-cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
+cifs_statfs(struct super_block *sb, struct kstatfs *buf)
 {
-       struct super_block *sb = dentry->d_sb;
        int xid; 
        int rc = -EOPNOTSUPP;
        struct cifs_sb_info *cifs_sb;
@@ -255,6 +259,7 @@ cifs_alloc_inode(struct super_block *sb)
        file data or metadata */
        cifs_inode->clientCanCacheRead = FALSE;
        cifs_inode->clientCanCacheAll = FALSE;
+       cifs_inode->vfs_inode.i_blksize = CIFS_MAX_MSGSIZE;
        cifs_inode->vfs_inode.i_blkbits = 14;  /* 2**14 = CIFS_MAX_MSGSIZE */
        cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;
        INIT_LIST_HEAD(&cifs_inode->openFileList);
@@ -401,14 +406,13 @@ static struct quotactl_ops cifs_quotactl_ops = {
 };
 #endif
 
-static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+static void cifs_umount_begin(struct super_block * sblock)
 {
        struct cifs_sb_info *cifs_sb;
        struct cifsTconInfo * tcon;
 
-       if (!(flags & MNT_FORCE))
-               return;
-       cifs_sb = CIFS_SB(vfsmnt->mnt_sb);
+       cifs_sb = CIFS_SB(sblock);
        if(cifs_sb == NULL)
                return;
 
@@ -420,7 +424,7 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
                tcon->tidStatus = CifsExiting;
        up(&tcon->tconSem);
 
-       /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
+       /* cancel_brl_requests(tcon); */
        /* cancel_notify_requests(tcon); */
        if(tcon->ses && tcon->ses->server)
        {
@@ -436,6 +440,7 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
 
        return;
 }
+#endif 
 
 static int cifs_remount(struct super_block *sb, int *flags, char *data)
 {
@@ -454,13 +459,15 @@ struct super_operations cifs_super_ops = {
    unless later we add lazy close of inodes or unless the kernel forgets to call
    us with the same number of releases (closes) as opens */
        .show_options = cifs_show_options,
+#ifdef CONFIG_CIFS_EXPERIMENTAL
        .umount_begin   = cifs_umount_begin,
+#endif
        .remount_fs = cifs_remount,
 };
 
-static int
+static struct super_block *
 cifs_get_sb(struct file_system_type *fs_type,
-           int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+           int flags, const char *dev_name, void *data)
 {
        int rc;
        struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
@@ -468,18 +475,18 @@ cifs_get_sb(struct file_system_type *fs_type,
        cFYI(1, ("Devname: %s flags: %d ", dev_name, flags));
 
        if (IS_ERR(sb))
-               return PTR_ERR(sb);
+               return sb;
 
        sb->s_flags = flags;
 
-       rc = cifs_read_super(sb, data, dev_name, flags & MS_SILENT ? 1 : 0);
+       rc = cifs_read_super(sb, data, dev_name, flags & MS_VERBOSE ? 1 : 0);
        if (rc) {
                up_write(&sb->s_umount);
                deactivate_super(sb);
-               return rc;
+               return ERR_PTR(rc);
        }
        sb->s_flags |= MS_ACTIVE;
-       return simple_set_mnt(mnt, sb);
+       return sb;
 }
 
 static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov,
@@ -576,7 +583,7 @@ struct inode_operations cifs_symlink_inode_ops = {
 #endif 
 };
 
-const struct file_operations cifs_file_ops = {
+struct file_operations cifs_file_ops = {
        .read = do_sync_read,
        .write = do_sync_write,
        .readv = generic_file_readv,
@@ -600,7 +607,7 @@ const struct file_operations cifs_file_ops = {
 #endif /* CONFIG_CIFS_EXPERIMENTAL */
 };
 
-const struct file_operations cifs_file_direct_ops = {
+struct file_operations cifs_file_direct_ops = {
        /* no mmap, no aio, no readv - 
           BB reevaluate whether they can be done with directio, no cache */
        .read = cifs_user_read,
@@ -619,7 +626,7 @@ const struct file_operations cifs_file_direct_ops = {
        .dir_notify = cifs_dir_notify,
 #endif /* CONFIG_CIFS_EXPERIMENTAL */
 };
-const struct file_operations cifs_file_nobrl_ops = {
+struct file_operations cifs_file_nobrl_ops = {
        .read = do_sync_read,
        .write = do_sync_write,
        .readv = generic_file_readv,
@@ -642,7 +649,7 @@ const struct file_operations cifs_file_nobrl_ops = {
 #endif /* CONFIG_CIFS_EXPERIMENTAL */
 };
 
-const struct file_operations cifs_file_direct_nobrl_ops = {
+struct file_operations cifs_file_direct_nobrl_ops = {
        /* no mmap, no aio, no readv - 
           BB reevaluate whether they can be done with directio, no cache */
        .read = cifs_user_read,
@@ -661,7 +668,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
 #endif /* CONFIG_CIFS_EXPERIMENTAL */
 };
 
-const struct file_operations cifs_dir_ops = {
+struct file_operations cifs_dir_ops = {
        .readdir = cifs_readdir,
        .release = cifs_closedir,
        .read    = generic_read_dir,
@@ -688,8 +695,7 @@ cifs_init_inodecache(void)
 {
        cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
                                              sizeof (struct cifsInodeInfo),
-                                             0, (SLAB_RECLAIM_ACCOUNT|
-                                               SLAB_MEM_SPREAD),
+                                             0, SLAB_RECLAIM_ACCOUNT,
                                              cifs_init_once, NULL);
        if (cifs_inode_cachep == NULL)
                return -ENOMEM;
@@ -731,8 +737,10 @@ cifs_init_request_bufs(void)
                cERROR(1,("cifs_min_rcv set to maximum (64)"));
        }
 
-       cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv,
-                                                 cifs_req_cachep);
+       cifs_req_poolp = mempool_create(cifs_min_rcv,
+                                       mempool_alloc_slab,
+                                       mempool_free_slab,
+                                       cifs_req_cachep);
 
        if(cifs_req_poolp == NULL) {
                kmem_cache_destroy(cifs_req_cachep);
@@ -762,8 +770,10 @@ cifs_init_request_bufs(void)
                cFYI(1,("cifs_min_small set to maximum (256)"));
        }
 
-       cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small,
-                                                    cifs_sm_req_cachep);
+       cifs_sm_req_poolp = mempool_create(cifs_min_small,
+                               mempool_alloc_slab,
+                               mempool_free_slab,
+                               cifs_sm_req_cachep);
 
        if(cifs_sm_req_poolp == NULL) {
                mempool_destroy(cifs_req_poolp);
@@ -797,8 +807,10 @@ cifs_init_mids(void)
        if (cifs_mid_cachep == NULL)
                return -ENOMEM;
 
-       /* 3 is a reasonable minimum number of simultaneous operations */
-       cifs_mid_poolp = mempool_create_slab_pool(3, cifs_mid_cachep);
+       cifs_mid_poolp = mempool_create(3 /* a reasonable min simultan opers */,
+                                       mempool_alloc_slab,
+                                       mempool_free_slab,
+                                       cifs_mid_cachep);
        if(cifs_mid_poolp == NULL) {
                kmem_cache_destroy(cifs_mid_cachep);
                return -ENOMEM;
@@ -837,6 +849,10 @@ static int cifs_oplock_thread(void * dummyarg)
        __u16  netfid;
        int rc;
 
+       daemonize("cifsoplockd");
+       allow_signal(SIGTERM);
+
+       oplockThread = current;
        do {
                if (try_to_freeze()) 
                        continue;
@@ -892,9 +908,9 @@ static int cifs_oplock_thread(void * dummyarg)
                        set_current_state(TASK_INTERRUPTIBLE);
                        schedule_timeout(1);  /* yield in case q were corrupt */
                }
-       } while (!kthread_should_stop());
-
-       return 0;
+       } while(!signal_pending(current));
+       oplockThread = NULL;
+       complete_and_exit (&cifs_oplock_exited, 0);
 }
 
 static int cifs_dnotify_thread(void * dummyarg)
@@ -902,8 +918,12 @@ static int cifs_dnotify_thread(void * dummyarg)
        struct list_head *tmp;
        struct cifsSesInfo *ses;
 
+       daemonize("cifsdnotifyd");
+       allow_signal(SIGTERM);
+
+       dnotifyThread = current;
        do {
-               if (try_to_freeze())
+               if(try_to_freeze())
                        continue;
                set_current_state(TASK_INTERRUPTIBLE);
                schedule_timeout(15*HZ);
@@ -919,9 +939,8 @@ static int cifs_dnotify_thread(void * dummyarg)
                                wake_up_all(&ses->server->response_q);
                }
                read_unlock(&GlobalSMBSeslock);
-       } while (!kthread_should_stop());
-
-       return 0;
+       } while(!signal_pending(current));
+       complete_and_exit (&cifs_dnotify_exited, 0);
 }
 
 static int __init
@@ -971,48 +990,32 @@ init_cifs(void)
        }
 
        rc = cifs_init_inodecache();
-       if (rc)
-               goto out_clean_proc;
-
-       rc = cifs_init_mids();
-       if (rc)
-               goto out_destroy_inodecache;
-
-       rc = cifs_init_request_bufs();
-       if (rc)
-               goto out_destroy_mids;
-
-       rc = register_filesystem(&cifs_fs_type);
-       if (rc)
-               goto out_destroy_request_bufs;
-
-       oplockThread = kthread_run(cifs_oplock_thread, NULL, "cifsoplockd");
-       if (IS_ERR(oplockThread)) {
-               rc = PTR_ERR(oplockThread);
-               cERROR(1,("error %d create oplock thread", rc));
-               goto out_unregister_filesystem;
-       }
-
-       dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
-       if (IS_ERR(dnotifyThread)) {
-               rc = PTR_ERR(dnotifyThread);
-               cERROR(1,("error %d create dnotify thread", rc));
-               goto out_stop_oplock_thread;
+       if (!rc) {
+               rc = cifs_init_mids();
+               if (!rc) {
+                       rc = cifs_init_request_bufs();
+                       if (!rc) {
+                               rc = register_filesystem(&cifs_fs_type);
+                               if (!rc) {                
+                                       rc = (int)kernel_thread(cifs_oplock_thread, NULL, 
+                                               CLONE_FS | CLONE_FILES | CLONE_VM);
+                                       if(rc > 0) {
+                                               rc = (int)kernel_thread(cifs_dnotify_thread, NULL,
+                                                       CLONE_FS | CLONE_FILES | CLONE_VM);
+                                               if(rc > 0)
+                                                       return 0;
+                                               else
+                                                       cERROR(1,("error %d create dnotify thread", rc));
+                                       } else {
+                                               cERROR(1,("error %d create oplock thread",rc));
+                                       }
+                               }
+                               cifs_destroy_request_bufs();
+                       }
+                       cifs_destroy_mids();
+               }
+               cifs_destroy_inodecache();
        }
-
-       return 0;
-
- out_stop_oplock_thread:
-       kthread_stop(oplockThread);
- out_unregister_filesystem:
-       unregister_filesystem(&cifs_fs_type);
- out_destroy_request_bufs:
-       cifs_destroy_request_bufs();
- out_destroy_mids:
-       cifs_destroy_mids();
- out_destroy_inodecache:
-       cifs_destroy_inodecache();
- out_clean_proc:
 #ifdef CONFIG_PROC_FS
        cifs_proc_clean();
 #endif
@@ -1030,8 +1033,14 @@ exit_cifs(void)
        cifs_destroy_inodecache();
        cifs_destroy_mids();
        cifs_destroy_request_bufs();
-       kthread_stop(oplockThread);
-       kthread_stop(dnotifyThread);
+       if(oplockThread) {
+               send_sig(SIGTERM, oplockThread, 1);
+               wait_for_completion(&cifs_oplock_exited);
+       }
+       if(dnotifyThread) {
+               send_sig(SIGTERM, dnotifyThread, 1);
+               wait_for_completion(&cifs_dnotify_exited);
+       }
 }
 
 MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");