[POWERPC] pasemi: Reset mpic on boot
[safe/jmp/linux-2.6] / fs / cifs / cifsfs.c
index 51e888f..faba4d6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifsfs.c
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2004
+ *   Copyright (C) International Business Machines  Corp., 2002,2007
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   Common Internet FileSystem (CIFS) client
@@ -34,6 +34,7 @@
 #include <linux/mempool.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
+#include <linux/freezer.h>
 #include "cifsfs.h"
 #include "cifspdu.h"
 #define DECLARE_GLOBALS_HERE
 
 #ifdef CONFIG_CIFS_QUOTA
 static struct quotactl_ops cifs_quotactl_ops;
-#endif
+#endif /* QUOTA */
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+extern struct export_operations cifs_export_ops;
+#endif /* EXPERIMENTAL */
 
 int cifsFYI = 0;
 int cifsERROR = 1;
@@ -61,9 +66,9 @@ unsigned int extended_security = CIFSSEC_DEF;
 unsigned int sign_CIFS_PDUs = 1;
 extern struct task_struct * oplockThread; /* remove sparse warning */
 struct task_struct * oplockThread = NULL;
-extern struct task_struct * dnotifyThread; /* remove sparse warning */
-struct task_struct * dnotifyThread = NULL;
-static struct super_operations cifs_super_ops; 
+/* extern struct task_struct * dnotifyThread; remove sparse warning */
+static struct task_struct * dnotifyThread = NULL;
+static const struct super_operations cifs_super_ops;
 unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
 module_param(CIFSMaxBufSize, int, 0);
 MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048");
@@ -81,7 +86,7 @@ extern mempool_t *cifs_sm_req_poolp;
 extern mempool_t *cifs_req_poolp;
 extern mempool_t *cifs_mid_poolp;
 
-extern kmem_cache_t *cifs_oplock_cachep;
+extern struct kmem_cache *cifs_oplock_cachep;
 
 static int
 cifs_read_super(struct super_block *sb, void *data,
@@ -90,8 +95,9 @@ cifs_read_super(struct super_block *sb, void *data,
        struct inode *inode;
        struct cifs_sb_info *cifs_sb;
        int rc = 0;
-
-       sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
+       
+       /* BB should we make this contingent on mount parm? */
+       sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
        sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
        cifs_sb = CIFS_SB(sb);
        if(cifs_sb == NULL)
@@ -108,6 +114,10 @@ cifs_read_super(struct super_block *sb, void *data,
 
        sb->s_magic = CIFS_MAGIC_NUMBER;
        sb->s_op = &cifs_super_ops;
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+       if(experimEnabled != 0)
+               sb->s_export_op = &cifs_export_ops;
+#endif /* EXPERIMENTAL */      
 /*     if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
            sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
 #ifdef CONFIG_CIFS_QUOTA
@@ -199,10 +209,12 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
     /* Only need to call the old QFSInfo if failed
     on newer one */
     if(rc)
-       rc = CIFSSMBQFSInfo(xid, pTcon, buf);
+       if(pTcon->ses->capabilities & CAP_NT_SMBS)
+               rc = CIFSSMBQFSInfo(xid, pTcon, buf); /* not supported by OS2 */
 
-       /* Old Windows servers do not support level 103, retry with level 
-          one if old server failed the previous call */ 
+       /* Some old Windows servers also do not support level 103, retry with
+          older level one if old server failed the previous call or we
+          bypassed it because we detected that this was an older LANMAN sess */
        if(rc)
                rc = SMBOldQFSInfo(xid, pTcon, buf);
        /*     
@@ -230,11 +242,11 @@ static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
                return generic_permission(inode, mask, NULL);
 }
 
-static kmem_cache_t *cifs_inode_cachep;
-static kmem_cache_t *cifs_req_cachep;
-static kmem_cache_t *cifs_mid_cachep;
-kmem_cache_t *cifs_oplock_cachep;
-static kmem_cache_t *cifs_sm_req_cachep;
+static struct kmem_cache *cifs_inode_cachep;
+static struct kmem_cache *cifs_req_cachep;
+static struct kmem_cache *cifs_mid_cachep;
+struct kmem_cache *cifs_oplock_cachep;
+static struct kmem_cache *cifs_sm_req_cachep;
 mempool_t *cifs_sm_req_poolp;
 mempool_t *cifs_req_poolp;
 mempool_t *cifs_mid_poolp;
@@ -243,7 +255,7 @@ static struct inode *
 cifs_alloc_inode(struct super_block *sb)
 {
        struct cifsInodeInfo *cifs_inode;
-       cifs_inode = kmem_cache_alloc(cifs_inode_cachep, SLAB_KERNEL);
+       cifs_inode = kmem_cache_alloc(cifs_inode_cachep, GFP_KERNEL);
        if (!cifs_inode)
                return NULL;
        cifs_inode->cifsAttrs = 0x20;   /* default */
@@ -254,9 +266,11 @@ 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;
+       
+       /* Can not set i_flags here - they get immediately overwritten
+          to zero by the VFS */
+/*     cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;*/
        INIT_LIST_HEAD(&cifs_inode->openFileList);
        return &cifs_inode->vfs_inode;
 }
@@ -281,6 +295,7 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
 
        if (cifs_sb) {
                if (cifs_sb->tcon) {
+/* BB add prepath to mount options displayed */
                        seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
                        if (cifs_sb->tcon->ses) {
                                if (cifs_sb->tcon->ses->userName)
@@ -437,13 +452,21 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
        return;
 }
 
+#ifdef CONFIG_CIFS_STATS2
+static int cifs_show_stats(struct seq_file *s, struct vfsmount *mnt)
+{
+       /* BB FIXME */
+       return 0;
+}
+#endif
+
 static int cifs_remount(struct super_block *sb, int *flags, char *data)
 {
        *flags |= MS_NODIRATIME;
        return 0;
 }
 
-static struct super_operations cifs_super_ops = {
+static const struct super_operations cifs_super_ops = {
        .read_inode = cifs_read_inode,
        .put_super = cifs_put_super,
        .statfs = cifs_statfs,
@@ -456,6 +479,9 @@ static struct super_operations cifs_super_ops = {
        .show_options = cifs_show_options,
        .umount_begin   = cifs_umount_begin,
        .remount_fs = cifs_remount,
+#ifdef CONFIG_CIFS_STATS2
+       .show_stats = cifs_show_stats,
+#endif
 };
 
 static int
@@ -482,25 +508,13 @@ cifs_get_sb(struct file_system_type *fs_type,
        return simple_set_mnt(mnt, sb);
 }
 
-static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov,
-                               unsigned long nr_segs, loff_t *ppos)
+static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+                                  unsigned long nr_segs, loff_t pos)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
        ssize_t written;
 
-       written = generic_file_writev(file, iov, nr_segs, ppos);
-       if (!CIFS_I(inode)->clientCanCacheAll)
-               filemap_fdatawrite(inode->i_mapping);
-       return written;
-}
-
-static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf,
-                                  size_t count, loff_t pos)
-{
-       struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
-       ssize_t written;
-
-       written = generic_file_aio_write(iocb, buf, count, pos);
+       written = generic_file_aio_write(iocb, iov, nr_segs, pos);
        if (!CIFS_I(inode)->clientCanCacheAll)
                filemap_fdatawrite(inode->i_mapping);
        return written;
@@ -510,7 +524,15 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
 {
        /* origin == SEEK_END => we must revalidate the cached file length */
        if (origin == SEEK_END) {
-               int retval = cifs_revalidate(file->f_dentry);
+               int retval;
+
+               /* some applications poll for the file length in this strange
+                  way so we must seek to end on non-oplocked files by
+                  setting the revalidate time to zero */
+               if(file->f_path.dentry->d_inode)                
+                       CIFS_I(file->f_path.dentry->d_inode)->time = 0;
+
+               retval = cifs_revalidate(file->f_path.dentry);
                if (retval < 0)
                        return (loff_t)retval;
        }
@@ -524,7 +546,7 @@ static struct file_system_type cifs_fs_type = {
        .kill_sb = kill_anon_super,
        /*  .fs_flags */
 };
-struct inode_operations cifs_dir_inode_ops = {
+const struct inode_operations cifs_dir_inode_ops = {
        .create = cifs_create,
        .lookup = cifs_lookup,
        .getattr = cifs_getattr,
@@ -546,7 +568,7 @@ struct inode_operations cifs_dir_inode_ops = {
 #endif
 };
 
-struct inode_operations cifs_file_inode_ops = {
+const struct inode_operations cifs_file_inode_ops = {
 /*     revalidate:cifs_revalidate, */
        .setattr = cifs_setattr,
        .getattr = cifs_getattr, /* do we need this anymore? */
@@ -560,7 +582,7 @@ struct inode_operations cifs_file_inode_ops = {
 #endif 
 };
 
-struct inode_operations cifs_symlink_inode_ops = {
+const struct inode_operations cifs_symlink_inode_ops = {
        .readlink = generic_readlink, 
        .follow_link = cifs_follow_link,
        .put_link = cifs_put_link,
@@ -579,8 +601,6 @@ struct inode_operations cifs_symlink_inode_ops = {
 const struct file_operations cifs_file_ops = {
        .read = do_sync_read,
        .write = do_sync_write,
-       .readv = generic_file_readv,
-       .writev = cifs_file_writev,
        .aio_read = generic_file_aio_read,
        .aio_write = cifs_file_aio_write,
        .open = cifs_open,
@@ -622,8 +642,6 @@ const struct file_operations cifs_file_direct_ops = {
 const struct file_operations cifs_file_nobrl_ops = {
        .read = do_sync_read,
        .write = do_sync_write,
-       .readv = generic_file_readv,
-       .writev = cifs_file_writev,
        .aio_read = generic_file_aio_read,
        .aio_write = cifs_file_aio_write,
        .open = cifs_open,
@@ -672,7 +690,7 @@ const struct file_operations cifs_dir_ops = {
 };
 
 static void
-cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags)
+cifs_init_once(void *inode, struct kmem_cache * cachep, unsigned long flags)
 {
        struct cifsInodeInfo *cifsi = inode;
 
@@ -700,8 +718,7 @@ cifs_init_inodecache(void)
 static void
 cifs_destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(cifs_inode_cachep))
-               printk(KERN_WARNING "cifs_inode_cache: error freeing\n");
+       kmem_cache_destroy(cifs_inode_cachep);
 }
 
 static int
@@ -779,13 +796,9 @@ static void
 cifs_destroy_request_bufs(void)
 {
        mempool_destroy(cifs_req_poolp);
-       if (kmem_cache_destroy(cifs_req_cachep))
-               printk(KERN_WARNING
-                      "cifs_destroy_request_cache: error not all structures were freed\n");
+       kmem_cache_destroy(cifs_req_cachep);
        mempool_destroy(cifs_sm_req_poolp);
-       if (kmem_cache_destroy(cifs_sm_req_cachep))
-               printk(KERN_WARNING
-                     "cifs_destroy_request_cache: cifs_small_rq free error\n");
+       kmem_cache_destroy(cifs_sm_req_cachep);
 }
 
 static int
@@ -820,13 +833,8 @@ static void
 cifs_destroy_mids(void)
 {
        mempool_destroy(cifs_mid_poolp);
-       if (kmem_cache_destroy(cifs_mid_cachep))
-               printk(KERN_WARNING
-                      "cifs_destroy_mids: error not all structures were freed\n");
-
-       if (kmem_cache_destroy(cifs_oplock_cachep))
-               printk(KERN_WARNING
-                      "error not all oplock structures were freed\n");
+       kmem_cache_destroy(cifs_mid_cachep);
+       kmem_cache_destroy(cifs_oplock_cachep);
 }
 
 static int cifs_oplock_thread(void * dummyarg)