From 497d5fc2d5ca3fb4af9929da4e2adc1fca45fc42 Mon Sep 17 00:00:00 2001 From: Steve French Date: Mon, 17 May 2004 11:53:34 -0500 Subject: [PATCH] switch to mempools for cifs request buf and mid allocation to avoid deadlocks in out of memory conditions --- fs/cifs/CHANGES | 5 +++++ fs/cifs/cifsfs.c | 34 +++++++++++++++++++++++++++++++--- fs/cifs/cifsfs.h | 2 +- fs/cifs/misc.c | 7 ++++--- fs/cifs/transport.c | 8 ++++---- 5 files changed, 45 insertions(+), 11 deletions(-) diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index b1cb9d982eceb..ec0ff7e3357a6 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,3 +1,8 @@ +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 ------------ Fix incomplete listings of large directories on Samba servers when Unix diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 17458b708b2fa..b017cb563224f 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "cifsfs.h" #include "cifspdu.h" #define DECLARE_GLOBALS_HERE @@ -39,7 +40,9 @@ #include "cifs_debug.h" #include "cifs_fs_sb.h" #include -#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 static struct quotactl_ops cifs_quotactl_ops; @@ -209,9 +212,11 @@ static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd) } static kmem_cache_t *cifs_inode_cachep; -kmem_cache_t *cifs_req_cachep; -kmem_cache_t *cifs_mid_cachep; +static kmem_cache_t *cifs_req_cachep; +static kmem_cache_t *cifs_mid_cachep; kmem_cache_t *cifs_oplock_cachep; +mempool_t *cifs_req_poolp; +mempool_t *cifs_mid_poolp; static struct inode * cifs_alloc_inode(struct super_block *sb) @@ -593,12 +598,23 @@ cifs_init_request_bufs(void) if (cifs_req_cachep == NULL) 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; } 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"); @@ -612,11 +628,22 @@ cifs_init_mids(void) SLAB_HWCACHE_ALIGN, NULL, NULL); if (cifs_mid_cachep == NULL) 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", sizeof (struct oplock_q_entry), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if (cifs_oplock_cachep == NULL) { kmem_cache_destroy(cifs_mid_cachep); + mempool_destroy(cifs_mid_poolp); return -ENOMEM; } @@ -629,6 +656,7 @@ cifs_destroy_mids(void) if (kmem_cache_destroy(cifs_mid_cachep)) printk(KERN_WARNING "cifs_destroy_mids: error not all structures were freed\n"); + mempool_destroy(cifs_mid_poolp); if (kmem_cache_destroy(cifs_oplock_cachep)) printk(KERN_WARNING "error not all oplock structures were freed\n"); diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 096f48b27bc0d..bd6547993a625 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -93,5 +93,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *, size_t, int); extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, 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 */ diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index ca96ffe2c80e6..9a31ed995522c 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -21,6 +21,7 @@ #include #include +#include #include "cifspdu.h" #include "cifsglob.h" #include "cifsproto.h" @@ -28,7 +29,7 @@ #include "smberr.h" #include "nterr.h" -extern kmem_cache_t *cifs_req_cachep; +extern mempool_t *cifs_req_poolp; extern struct task_struct * oplockThread; __u16 GlobalMid; /* multiplex id - rotating counter */ @@ -153,7 +154,7 @@ cifs_buf_get(void) albeit slightly larger than necessary and maxbuffersize defaults to this and can not be bigger */ 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 */ if (ret_buf) { @@ -172,7 +173,7 @@ cifs_buf_release(void *buf_to_free) cFYI(1, ("Null buffer passed to cifs_buf_release")); return; } - kmem_cache_free(cifs_req_cachep, buf_to_free); + mempool_free(buf_to_free,cifs_req_poolp); atomic_dec(&bufAllocCount); return; diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index aaa78992a045d..91a6baf0831d1 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -25,12 +25,13 @@ #include #include #include +#include #include "cifspdu.h" #include "cifsglob.h" #include "cifsproto.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; struct mid_q_entry * @@ -47,8 +48,7 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) return NULL; } - temp = (struct mid_q_entry *) kmem_cache_alloc(cifs_mid_cachep, - SLAB_KERNEL); + temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,SLAB_KERNEL | SLAB_NOFS); if (temp == NULL) return temp; else { @@ -79,7 +79,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry) atomic_dec(&midCount); spin_unlock(&GlobalMid_Lock); cifs_buf_release(midEntry->resp_buf); - kmem_cache_free(cifs_mid_cachep, midEntry); + mempool_free(midEntry, cifs_mid_poolp); } struct oplock_q_entry * -- 2.53.0