]> err.no Git - linux-2.6/blobdiff - fs/cifs/cifsfs.c
[CIFS] DFS support patchset: Added mountdata
[linux-2.6] / fs / cifs / cifsfs.c
index 093beaa3900de3321a2062143daeb04f7e6b17b2..93e107883a616fa31172909a371f9d4ab208490b 100644 (file)
@@ -44,6 +44,7 @@
 #include "cifs_fs_sb.h"
 #include <linux/mm.h>
 #include <linux/key-type.h>
+#include "dns_resolve.h"
 #include "cifs_spnego.h"
 #define CIFS_MAGIC_NUMBER 0xFF534D42   /* the first four bytes of SMB PDUs */
 
@@ -96,6 +97,9 @@ cifs_read_super(struct super_block *sb, void *data,
 {
        struct inode *inode;
        struct cifs_sb_info *cifs_sb;
+#ifdef CONFIG_CIFS_DFS_UPCALL
+       int len;
+#endif
        int rc = 0;
 
        /* BB should we make this contingent on mount parm? */
@@ -105,6 +109,25 @@ cifs_read_super(struct super_block *sb, void *data,
        if (cifs_sb == NULL)
                return -ENOMEM;
 
+#ifdef CONFIG_CIFS_DFS_UPCALL
+       /* copy mount params to sb for use in submounts */
+       /* BB: should we move this after the mount so we
+        * do not have to do the copy on failed mounts?
+        * BB: May be it is better to do simple copy before
+        * complex operation (mount), and in case of fail
+        * just exit instead of doing mount and attempting
+        * undo it if this copy fails?*/
+       len = strlen(data);
+       cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL);
+       if (cifs_sb->mountdata == NULL) {
+               kfree(sb->s_fs_info);
+               sb->s_fs_info = NULL;
+               return -ENOMEM;
+       }
+       strncpy(cifs_sb->mountdata, data, len + 1);
+       cifs_sb->mountdata[len] = '\0';
+#endif
+
        rc = cifs_mount(sb, cifs_sb, data, devname);
 
        if (rc) {
@@ -154,6 +177,12 @@ out_no_root:
 
 out_mount_failed:
        if (cifs_sb) {
+#ifdef CONFIG_CIFS_DFS_UPCALL
+               if (cifs_sb->mountdata) {
+                       kfree(cifs_sb->mountdata);
+                       cifs_sb->mountdata = NULL;
+               }
+#endif
                if (cifs_sb->local_nls)
                        unload_nls(cifs_sb->local_nls);
                kfree(cifs_sb);
@@ -177,6 +206,13 @@ cifs_put_super(struct super_block *sb)
        if (rc) {
                cERROR(1, ("cifs_umount failed with return code %d", rc));
        }
+#ifdef CONFIG_CIFS_DFS_UPCALL
+       if (cifs_sb->mountdata) {
+               kfree(cifs_sb->mountdata);
+               cifs_sb->mountdata = NULL;
+       }
+#endif
+
        unload_nls(cifs_sb->local_nls);
        kfree(cifs_sb);
        return;
@@ -552,7 +588,7 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
        return remote_llseek(file, offset, origin);
 }
 
-static struct file_system_type cifs_fs_type = {
+struct file_system_type cifs_fs_type = {
        .owner = THIS_MODULE,
        .name = "cifs",
        .get_sb = cifs_get_sb,
@@ -1014,12 +1050,17 @@ init_cifs(void)
        rc = register_key_type(&cifs_spnego_key_type);
        if (rc)
                goto out_unregister_filesystem;
+#endif
+#ifdef CONFIG_CIFS_DFS_UPCALL
+       rc = register_key_type(&key_type_dns_resolver);
+       if (rc)
+               goto out_unregister_key_type;
 #endif
        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_key_type;
+               goto out_unregister_dfs_key_type;
        }
 
        dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
@@ -1033,7 +1074,11 @@ init_cifs(void)
 
  out_stop_oplock_thread:
        kthread_stop(oplockThread);
+ out_unregister_dfs_key_type:
+#ifdef CONFIG_CIFS_DFS_UPCALL
+       unregister_key_type(&key_type_dns_resolver);
  out_unregister_key_type:
+#endif
 #ifdef CONFIG_CIFS_UPCALL
        unregister_key_type(&cifs_spnego_key_type);
  out_unregister_filesystem:
@@ -1059,6 +1104,9 @@ exit_cifs(void)
 #ifdef CONFIG_PROC_FS
        cifs_proc_clean();
 #endif
+#ifdef CONFIG_CIFS_DFS_UPCALL
+       unregister_key_type(&key_type_dns_resolver);
+#endif
 #ifdef CONFIG_CIFS_UPCALL
        unregister_key_type(&cifs_spnego_key_type);
 #endif