]> err.no Git - linux-2.6/blobdiff - fs/cifs/cifsfs.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
[linux-2.6] / fs / cifs / cifsfs.c
index c7c3521aa7cddc601170b4f6e716e996f98d62c7..e9f4ec7010926fb76e4808d3e4ed1bd0ab7f7cb5 100644 (file)
 #include "cifs_debug.h"
 #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 */
 
 #ifdef CONFIG_CIFS_QUOTA
 static struct quotactl_ops cifs_quotactl_ops;
 #endif /* QUOTA */
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-extern struct export_operations cifs_export_ops;
-#endif /* EXPERIMENTAL */
-
 int cifsFYI = 0;
 int cifsERROR = 1;
 int traceSMB = 0;
@@ -98,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? */
@@ -107,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) {
@@ -156,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);
@@ -179,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;
@@ -268,6 +302,7 @@ cifs_alloc_inode(struct super_block *sb)
        cifs_inode->cifsAttrs = 0x20;   /* default */
        atomic_set(&cifs_inode->inUse, 0);
        cifs_inode->time = 0;
+       cifs_inode->write_behind_rc = 0;
        /* Until the file is open and we have gotten oplock
        info back from the server, can not assume caching of
        file data or metadata */
@@ -312,15 +347,15 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
                                        seq_printf(s, ",domain=%s",
                                           cifs_sb->tcon->ses->domainName);
                        }
+                       if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
+                          !(cifs_sb->tcon->unix_ext))
+                               seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
+                       if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
+                          !(cifs_sb->tcon->unix_ext))
+                               seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
                }
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
                        seq_printf(s, ",posixpaths");
-               if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
-                  !(cifs_sb->tcon->unix_ext))
-                       seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
-               if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
-                  !(cifs_sb->tcon->unix_ext))
-                       seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
                seq_printf(s, ",rsize=%d", cifs_sb->rsize);
                seq_printf(s, ",wsize=%d", cifs_sb->wsize);
        }
@@ -436,6 +471,10 @@ static void cifs_umount_begin(struct vfsmount *vfsmnt, int flags)
        struct cifs_sb_info *cifs_sb;
        struct cifsTconInfo *tcon;
 
+#ifdef CONFIG_CIFS_DFS_UPCALL
+       dfs_shrink_umount_helper(vfsmnt);
+#endif /* CONFIG CIFS_DFS_UPCALL */
+
        if (!(flags & MNT_FORCE))
                return;
        cifs_sb = CIFS_SB(vfsmnt->mnt_sb);
@@ -553,7 +592,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,
@@ -704,7 +743,7 @@ const struct file_operations cifs_dir_ops = {
 };
 
 static void
-cifs_init_once(void *inode, struct kmem_cache *cachep, unsigned long flags)
+cifs_init_once(struct kmem_cache *cachep, void *inode)
 {
        struct cifsInodeInfo *cifsi = inode;
 
@@ -854,7 +893,7 @@ static int cifs_oplock_thread(void *dummyarg)
        struct cifsTconInfo *pTcon;
        struct inode *inode;
        __u16  netfid;
-       int rc;
+       int rc, waitrc = 0;
 
        set_freezable();
        do {
@@ -886,9 +925,11 @@ static int cifs_oplock_thread(void *dummyarg)
                                           filemap_fdatawrite(inode->i_mapping);
                                        if (CIFS_I(inode)->clientCanCacheRead
                                                                         == 0) {
-                                               filemap_fdatawait(inode->i_mapping);
+                                               waitrc = filemap_fdatawait(inode->i_mapping);
                                                invalidate_remote_inode(inode);
                                        }
+                                       if (rc == 0)
+                                               rc = waitrc;
                                } else
                                        rc = 0;
                                /* mutex_unlock(&inode->i_mutex);*/
@@ -1009,12 +1050,21 @@ init_cifs(void)
        rc = register_filesystem(&cifs_fs_type);
        if (rc)
                goto out_destroy_request_bufs;
-
+#ifdef CONFIG_CIFS_UPCALL
+       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_filesystem;
+               goto out_unregister_dfs_key_type;
        }
 
        dnotifyThread = kthread_run(cifs_dnotify_thread, NULL, "cifsdnotifyd");
@@ -1028,7 +1078,15 @@ 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:
+#endif
        unregister_filesystem(&cifs_fs_type);
  out_destroy_request_bufs:
        cifs_destroy_request_bufs();
@@ -1049,6 +1107,12 @@ exit_cifs(void)
        cFYI(0, ("exit_cifs"));
 #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
        unregister_filesystem(&cifs_fs_type);
        cifs_destroy_inodecache();