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 *);
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;
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 {
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) {
.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 = {
.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
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);
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;
}
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
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) {