Commit 497d5fc2 authored by Steve French's avatar Steve French Committed by Steve French

switch to mempools for cifs request buf and mid allocation to avoid deadlocks...

switch to mempools for cifs request buf and mid allocation to avoid deadlocks in out of memory conditions
parent b3a9bd1f
Version 1.15
------------
Change to mempools for alloc smb request buffers and multiplex structs
to better handle low memory problems (and potential deadlocks).
Version 1.14 Version 1.14
------------ ------------
Fix incomplete listings of large directories on Samba servers when Unix Fix incomplete listings of large directories on Samba servers when Unix
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/vfs.h> #include <linux/vfs.h>
#include <linux/mempool.h>
#include "cifsfs.h" #include "cifsfs.h"
#include "cifspdu.h" #include "cifspdu.h"
#define DECLARE_GLOBALS_HERE #define DECLARE_GLOBALS_HERE
...@@ -39,7 +40,9 @@ ...@@ -39,7 +40,9 @@
#include "cifs_debug.h" #include "cifs_debug.h"
#include "cifs_fs_sb.h" #include "cifs_fs_sb.h"
#include <linux/mm.h> #include <linux/mm.h>
#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of all SMB PDUs */ #define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
/* BB when mempool_resize is added back in, we will resize pool on new mount */
#define CIFS_MIN_RCV_POOL 11 /* enough for progress to five servers */
#ifdef CIFS_QUOTA #ifdef CIFS_QUOTA
static struct quotactl_ops cifs_quotactl_ops; static struct quotactl_ops cifs_quotactl_ops;
...@@ -209,9 +212,11 @@ static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd) ...@@ -209,9 +212,11 @@ static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
} }
static kmem_cache_t *cifs_inode_cachep; static kmem_cache_t *cifs_inode_cachep;
kmem_cache_t *cifs_req_cachep; static kmem_cache_t *cifs_req_cachep;
kmem_cache_t *cifs_mid_cachep; static kmem_cache_t *cifs_mid_cachep;
kmem_cache_t *cifs_oplock_cachep; kmem_cache_t *cifs_oplock_cachep;
mempool_t *cifs_req_poolp;
mempool_t *cifs_mid_poolp;
static struct inode * static struct inode *
cifs_alloc_inode(struct super_block *sb) cifs_alloc_inode(struct super_block *sb)
...@@ -593,12 +598,23 @@ cifs_init_request_bufs(void) ...@@ -593,12 +598,23 @@ cifs_init_request_bufs(void)
if (cifs_req_cachep == NULL) if (cifs_req_cachep == NULL)
return -ENOMEM; return -ENOMEM;
cifs_req_poolp = mempool_create(CIFS_MIN_RCV_POOL,
mempool_alloc_slab,
mempool_free_slab,
cifs_req_cachep);
if(cifs_req_poolp == NULL) {
kmem_cache_destroy(cifs_req_cachep);
return -ENOMEM;
}
return 0; return 0;
} }
static void static void
cifs_destroy_request_bufs(void) cifs_destroy_request_bufs(void)
{ {
mempool_destroy(cifs_req_poolp);
if (kmem_cache_destroy(cifs_req_cachep)) if (kmem_cache_destroy(cifs_req_cachep))
printk(KERN_WARNING printk(KERN_WARNING
"cifs_destroy_request_cache: error not all structures were freed\n"); "cifs_destroy_request_cache: error not all structures were freed\n");
...@@ -612,11 +628,22 @@ cifs_init_mids(void) ...@@ -612,11 +628,22 @@ cifs_init_mids(void)
SLAB_HWCACHE_ALIGN, NULL, NULL); SLAB_HWCACHE_ALIGN, NULL, NULL);
if (cifs_mid_cachep == NULL) if (cifs_mid_cachep == NULL)
return -ENOMEM; return -ENOMEM;
cifs_mid_poolp = mempool_create(3 /* a reasonable min simultan opers */,
mempool_alloc_slab,
mempool_free_slab,
cifs_mid_cachep);
if(cifs_mid_poolp == NULL) {
kmem_cache_destroy(cifs_mid_cachep);
return -ENOMEM;
}
cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs", cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs",
sizeof (struct oplock_q_entry), 0, sizeof (struct oplock_q_entry), 0,
SLAB_HWCACHE_ALIGN, NULL, NULL); SLAB_HWCACHE_ALIGN, NULL, NULL);
if (cifs_oplock_cachep == NULL) { if (cifs_oplock_cachep == NULL) {
kmem_cache_destroy(cifs_mid_cachep); kmem_cache_destroy(cifs_mid_cachep);
mempool_destroy(cifs_mid_poolp);
return -ENOMEM; return -ENOMEM;
} }
...@@ -629,6 +656,7 @@ cifs_destroy_mids(void) ...@@ -629,6 +656,7 @@ cifs_destroy_mids(void)
if (kmem_cache_destroy(cifs_mid_cachep)) if (kmem_cache_destroy(cifs_mid_cachep))
printk(KERN_WARNING printk(KERN_WARNING
"cifs_destroy_mids: error not all structures were freed\n"); "cifs_destroy_mids: error not all structures were freed\n");
mempool_destroy(cifs_mid_poolp);
if (kmem_cache_destroy(cifs_oplock_cachep)) if (kmem_cache_destroy(cifs_oplock_cachep))
printk(KERN_WARNING printk(KERN_WARNING
"error not all oplock structures were freed\n"); "error not all oplock structures were freed\n");
......
...@@ -93,5 +93,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *, ...@@ -93,5 +93,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int); size_t, int);
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
#define CIFS_VERSION "1.14" #define CIFS_VERSION "1.15"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/mempool.h>
#include "cifspdu.h" #include "cifspdu.h"
#include "cifsglob.h" #include "cifsglob.h"
#include "cifsproto.h" #include "cifsproto.h"
...@@ -28,7 +29,7 @@ ...@@ -28,7 +29,7 @@
#include "smberr.h" #include "smberr.h"
#include "nterr.h" #include "nterr.h"
extern kmem_cache_t *cifs_req_cachep; extern mempool_t *cifs_req_poolp;
extern struct task_struct * oplockThread; extern struct task_struct * oplockThread;
__u16 GlobalMid; /* multiplex id - rotating counter */ __u16 GlobalMid; /* multiplex id - rotating counter */
...@@ -153,7 +154,7 @@ cifs_buf_get(void) ...@@ -153,7 +154,7 @@ cifs_buf_get(void)
albeit slightly larger than necessary and maxbuffersize albeit slightly larger than necessary and maxbuffersize
defaults to this and can not be bigger */ defaults to this and can not be bigger */
ret_buf = ret_buf =
(struct smb_hdr *) kmem_cache_alloc(cifs_req_cachep, SLAB_KERNEL | SLAB_NOFS); (struct smb_hdr *) mempool_alloc(cifs_req_poolp, SLAB_KERNEL | SLAB_NOFS);
/* clear the first few header bytes */ /* clear the first few header bytes */
if (ret_buf) { if (ret_buf) {
...@@ -172,7 +173,7 @@ cifs_buf_release(void *buf_to_free) ...@@ -172,7 +173,7 @@ cifs_buf_release(void *buf_to_free)
cFYI(1, ("Null buffer passed to cifs_buf_release")); cFYI(1, ("Null buffer passed to cifs_buf_release"));
return; return;
} }
kmem_cache_free(cifs_req_cachep, buf_to_free); mempool_free(buf_to_free,cifs_req_poolp);
atomic_dec(&bufAllocCount); atomic_dec(&bufAllocCount);
return; return;
......
...@@ -25,12 +25,13 @@ ...@@ -25,12 +25,13 @@
#include <linux/net.h> #include <linux/net.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <linux/mempool.h>
#include "cifspdu.h" #include "cifspdu.h"
#include "cifsglob.h" #include "cifsglob.h"
#include "cifsproto.h" #include "cifsproto.h"
#include "cifs_debug.h" #include "cifs_debug.h"
extern kmem_cache_t *cifs_mid_cachep; extern mempool_t *cifs_mid_poolp;
extern kmem_cache_t *cifs_oplock_cachep; extern kmem_cache_t *cifs_oplock_cachep;
struct mid_q_entry * struct mid_q_entry *
...@@ -47,8 +48,7 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) ...@@ -47,8 +48,7 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
return NULL; return NULL;
} }
temp = (struct mid_q_entry *) kmem_cache_alloc(cifs_mid_cachep, temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,SLAB_KERNEL | SLAB_NOFS);
SLAB_KERNEL);
if (temp == NULL) if (temp == NULL)
return temp; return temp;
else { else {
...@@ -79,7 +79,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry) ...@@ -79,7 +79,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
atomic_dec(&midCount); atomic_dec(&midCount);
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
cifs_buf_release(midEntry->resp_buf); cifs_buf_release(midEntry->resp_buf);
kmem_cache_free(cifs_mid_cachep, midEntry); mempool_free(midEntry, cifs_mid_poolp);
} }
struct oplock_q_entry * struct oplock_q_entry *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment