vserver 1.9.5.x5
[linux-2.6.git] / fs / cifs / cifsfs.c
index 729cdba..b0884aa 100644 (file)
@@ -50,15 +50,27 @@ int cifsFYI = 0;
 int cifsERROR = 1;
 int traceSMB = 0;
 unsigned int oplockEnabled = 1;
-unsigned int quotaEnabled = 0;
+unsigned int experimEnabled = 0;
 unsigned int linuxExtEnabled = 1;
 unsigned int lookupCacheEnabled = 1;
 unsigned int multiuser_mount = 0;
 unsigned int extended_security = 0;
 unsigned int ntlmv2_support = 0;
 unsigned int sign_CIFS_PDUs = 1;
-unsigned int CIFSMaximumBufferSize = CIFS_MAX_MSGSIZE;
 struct task_struct * oplockThread = NULL;
+unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
+module_param(CIFSMaxBufSize, int, CIFS_MAX_MSGSIZE);
+MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048");
+unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
+module_param(cifs_min_rcv, int, CIFS_MIN_RCV_POOL);
+MODULE_PARM_DESC(cifs_min_rcv,"Network buffers in pool. Default: 4 Range: 1 to 64");
+unsigned int cifs_min_small = 30;
+module_param(cifs_min_small, int, 30);
+MODULE_PARM_DESC(cifs_small_rcv,"Small network buffers in pool. Default: 30 Range: 2 to 256");
+unsigned int cifs_max_pending = CIFS_MAX_REQ;
+module_param(cifs_max_pending, int, CIFS_MAX_REQ);
+MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256");
+
 
 extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
                        const char *);
@@ -200,13 +212,15 @@ static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
                on the client (above and beyond ACL on servers) for  
                servers which do not support setting and viewing mode bits,
                so allowing client to check permissions is useful */ 
-               return vfs_permission(inode, mask);
+               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;
+mempool_t *cifs_sm_req_poolp;
 mempool_t *cifs_req_poolp;
 mempool_t *cifs_mid_poolp;
 
@@ -431,6 +445,20 @@ cifs_read_wrapper(struct file * file, char __user *read_data, size_t read_size,
                return -EIO;
 
        cFYI(1,("In read_wrapper size %zd at %lld",read_size,*poffset));
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+       /* check whether we can cache writes locally */
+       if(file->f_dentry->d_sb) {
+               struct cifs_sb_info *cifs_sb;
+               cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+               if(cifs_sb != NULL) {
+                       if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+                               return cifs_user_read(file,read_data,
+                                                       read_size,poffset);
+               }
+       }
+#endif /* CIFS_EXPERIMENTAL */
+
        if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) {
                return generic_file_read(file,read_data,read_size,poffset);
        } else {
@@ -463,7 +491,19 @@ cifs_write_wrapper(struct file * file, const char __user *write_data,
 
        cFYI(1,("In write_wrapper size %zd at %lld",write_size,*poffset));
 
+#ifdef CONFIG_CIFS_EXPERIMENTAL    /* BB fixme - fix user char * to kernel char * mapping here BB */
        /* check whether we can cache writes locally */
+       if(file->f_dentry->d_sb) {
+               struct cifs_sb_info *cifs_sb;
+               cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+               if(cifs_sb != NULL) {
+                       if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
+                               return cifs_user_write(file,write_data,
+                                                       write_size,poffset);
+                       }
+               }
+       }
+#endif /* CIFS_EXPERIMENTAL */
        written = generic_file_write(file,write_data,write_size,poffset);
        if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll)  {
                if(file->f_dentry->d_inode->i_mapping) {
@@ -495,6 +535,12 @@ struct inode_operations cifs_dir_inode_ops = {
        .setattr = cifs_setattr,
        .symlink = cifs_symlink,
        .mknod   = cifs_mknod,
+#ifdef CONFIG_CIFS_XATTR
+       .setxattr = cifs_setxattr,
+       .getxattr = cifs_getxattr,
+       .listxattr = cifs_listxattr,
+       .removexattr = cifs_removexattr,
+#endif
 };
 
 struct inode_operations cifs_file_inode_ops = {
@@ -537,14 +583,18 @@ struct file_operations cifs_file_ops = {
        .flush = cifs_flush,
        .mmap  = cifs_file_mmap,
        .sendfile = generic_file_sendfile,
+#ifdef CONFIG_CIFS_EXPERIMENTAL
        .dir_notify = cifs_dir_notify,
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
 };
 
 struct file_operations cifs_dir_ops = {
        .readdir = cifs_readdir,
        .release = cifs_closedir,
        .read    = generic_read_dir,
+#ifdef CONFIG_CIFS_EXPERIMENTAL
        .dir_notify = cifs_dir_notify,
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
 };
 
 static void
@@ -582,14 +632,31 @@ cifs_destroy_inodecache(void)
 static int
 cifs_init_request_bufs(void)
 {
+       if(CIFSMaxBufSize < 8192) {
+       /* Buffer size can not be smaller than 2 * PATH_MAX since maximum
+       Unicode path name has to fit in any SMB/CIFS path based frames */
+               CIFSMaxBufSize = 8192;
+       } else if (CIFSMaxBufSize > 1024*127) {
+               CIFSMaxBufSize = 1024 * 127;
+       } else {
+               CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/
+       }
+/*     cERROR(1,("CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize)); */
        cifs_req_cachep = kmem_cache_create("cifs_request",
-                                           CIFS_MAX_MSGSIZE +
+                                           CIFSMaxBufSize +
                                            MAX_CIFS_HDR_SIZE, 0,
                                            SLAB_HWCACHE_ALIGN, NULL, NULL);
        if (cifs_req_cachep == NULL)
                return -ENOMEM;
 
-       cifs_req_poolp = mempool_create(CIFS_MIN_RCV_POOL,
+       if(cifs_min_rcv < 1)
+               cifs_min_rcv = 1;
+       else if (cifs_min_rcv > 64) {
+               cifs_min_rcv = 64;
+               cFYI(1,("cifs_min_rcv set to maximum (64)"));
+       }
+
+       cifs_req_poolp = mempool_create(cifs_min_rcv,
                                        mempool_alloc_slab,
                                        mempool_free_slab,
                                        cifs_req_cachep);
@@ -598,6 +665,40 @@ cifs_init_request_bufs(void)
                kmem_cache_destroy(cifs_req_cachep);
                return -ENOMEM;
        }
+       /* 256 (MAX_CIFS_HDR_SIZE bytes is enough for most SMB responses and
+       almost all handle based requests (but not write response, nor is it
+       sufficient for path based requests).  A smaller size would have
+       been more efficient (compacting multiple slab items on one 4k page) 
+       for the case in which debug was on, but this larger size allows
+       more SMBs to use small buffer alloc and is still much more
+       efficient to alloc 1 per page off the slab compared to 17K (5page) 
+       alloc of large cifs buffers even when page debugging is on */
+       cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq",
+                       MAX_CIFS_HDR_SIZE, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+       if (cifs_sm_req_cachep == NULL) {
+               mempool_destroy(cifs_req_poolp);
+               kmem_cache_destroy(cifs_req_cachep);
+               return -ENOMEM;              
+       }
+
+       if(cifs_min_small < 2)
+               cifs_min_small = 2;
+       else if (cifs_min_small > 256) {
+               cifs_min_small = 256;
+               cFYI(1,("cifs_min_small set to maximum (256)"));
+       }
+
+       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);
+               kmem_cache_destroy(cifs_req_cachep);
+               kmem_cache_destroy(cifs_sm_req_cachep);
+               return -ENOMEM;
+       }
 
        return 0;
 }
@@ -609,6 +710,10 @@ cifs_destroy_request_bufs(void)
        if (kmem_cache_destroy(cifs_req_cachep))
                printk(KERN_WARNING
                       "cifs_destroy_request_cache: error not all structures were freed\n");
+       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");
 }
 
 static int
@@ -748,8 +853,16 @@ init_cifs(void)
        GlobalCurrentXid = 0;
        GlobalTotalActiveXid = 0;
        GlobalMaxActiveXid = 0;
-       GlobalSMBSeslock = RW_LOCK_UNLOCKED;
-       GlobalMid_Lock = SPIN_LOCK_UNLOCKED;
+       rwlock_init(&GlobalSMBSeslock);
+       spin_lock_init(&GlobalMid_Lock);
+
+       if(cifs_max_pending < 2) {
+               cifs_max_pending = 2;
+               cFYI(1,("cifs_max_pending set to min of 2"));
+       } else if(cifs_max_pending > 256) {
+               cifs_max_pending = 256;
+               cFYI(1,("cifs_max_pending set to max of 256"));
+       }
 
        rc = cifs_init_inodecache();
        if (!rc) {