svcrdma: Change WR context get/put to use the kmem cache
authorTom Tucker <tom@opengridcomputing.com>
Wed, 28 May 2008 20:14:02 +0000 (15:14 -0500)
committerTom Tucker <tom@opengridcomputing.com>
Wed, 2 Jul 2008 20:02:02 +0000 (15:02 -0500)
Change the WR context pool to be shared across mount points. This
reduces the RDMA transport memory footprint significantly since
idle mounts don't consume WR context memory.

Signed-off-by: Tom Tucker <tom@opengridcomputing.com>
include/linux/sunrpc/svc_rdma.h
net/sunrpc/xprtrdma/svc_rdma_transport.c

index d8d74c4..ef2e3a2 100644 (file)
@@ -73,7 +73,6 @@ extern atomic_t rdma_stat_sq_prod;
 struct svc_rdma_op_ctxt {
        struct svc_rdma_op_ctxt *read_hdr;
        int hdr_count;
-       struct list_head free_list;
        struct xdr_buf arg;
        struct list_head dto_q;
        enum ib_wr_opcode wr_op;
@@ -131,11 +130,6 @@ struct svcxprt_rdma {
 
        atomic_t             sc_dma_used;
        atomic_t             sc_ctxt_used;
-       struct list_head     sc_ctxt_free;
-       int                  sc_ctxt_cnt;
-       int                  sc_ctxt_bump;
-       int                  sc_ctxt_max;
-       spinlock_t           sc_ctxt_lock;
        struct list_head     sc_rq_dto_q;
        spinlock_t           sc_rq_dto_lock;
        struct ib_qp         *sc_qp;
index 80104f4..19ddc38 100644 (file)
@@ -84,69 +84,23 @@ struct svc_xprt_class svc_rdma_class = {
        .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP,
 };
 
-static int rdma_bump_context_cache(struct svcxprt_rdma *xprt)
-{
-       int target;
-       int at_least_one = 0;
-       struct svc_rdma_op_ctxt *ctxt;
-
-       target = min(xprt->sc_ctxt_cnt + xprt->sc_ctxt_bump,
-                    xprt->sc_ctxt_max);
-
-       spin_lock_bh(&xprt->sc_ctxt_lock);
-       while (xprt->sc_ctxt_cnt < target) {
-               xprt->sc_ctxt_cnt++;
-               spin_unlock_bh(&xprt->sc_ctxt_lock);
-
-               ctxt = kmalloc(sizeof(*ctxt), GFP_KERNEL);
-
-               spin_lock_bh(&xprt->sc_ctxt_lock);
-               if (ctxt) {
-                       at_least_one = 1;
-                       INIT_LIST_HEAD(&ctxt->free_list);
-                       list_add(&ctxt->free_list, &xprt->sc_ctxt_free);
-               } else {
-                       /* kmalloc failed...give up for now */
-                       xprt->sc_ctxt_cnt--;
-                       break;
-               }
-       }
-       spin_unlock_bh(&xprt->sc_ctxt_lock);
-       dprintk("svcrdma: sc_ctxt_max=%d, sc_ctxt_cnt=%d\n",
-               xprt->sc_ctxt_max, xprt->sc_ctxt_cnt);
-       return at_least_one;
-}
+/* WR context cache. Created in svc_rdma.c  */
+extern struct kmem_cache *svc_rdma_ctxt_cachep;
 
 struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt)
 {
        struct svc_rdma_op_ctxt *ctxt;
 
        while (1) {
-               spin_lock_bh(&xprt->sc_ctxt_lock);
-               if (unlikely(list_empty(&xprt->sc_ctxt_free))) {
-                       /* Try to bump my cache. */
-                       spin_unlock_bh(&xprt->sc_ctxt_lock);
-
-                       if (rdma_bump_context_cache(xprt))
-                               continue;
-
-                       printk(KERN_INFO "svcrdma: sleeping waiting for "
-                              "context memory on xprt=%p\n",
-                              xprt);
-                       schedule_timeout_uninterruptible(msecs_to_jiffies(500));
-                       continue;
-               }
-               ctxt = list_entry(xprt->sc_ctxt_free.next,
-                                 struct svc_rdma_op_ctxt,
-                                 free_list);
-               list_del_init(&ctxt->free_list);
-               spin_unlock_bh(&xprt->sc_ctxt_lock);
-               ctxt->xprt = xprt;
-               INIT_LIST_HEAD(&ctxt->dto_q);
-               ctxt->count = 0;
-               atomic_inc(&xprt->sc_ctxt_used);
-               break;
+               ctxt = kmem_cache_alloc(svc_rdma_ctxt_cachep, GFP_KERNEL);
+               if (ctxt)
+                       break;
+               schedule_timeout_uninterruptible(msecs_to_jiffies(500));
        }
+       ctxt->xprt = xprt;
+       INIT_LIST_HEAD(&ctxt->dto_q);
+       ctxt->count = 0;
+       atomic_inc(&xprt->sc_ctxt_used);
        return ctxt;
 }
 
@@ -174,9 +128,7 @@ void svc_rdma_put_context(struct svc_rdma_op_ctxt *ctxt, int free_pages)
                for (i = 0; i < ctxt->count; i++)
                        put_page(ctxt->pages[i]);
 
-       spin_lock_bh(&xprt->sc_ctxt_lock);
-       list_add(&ctxt->free_list, &xprt->sc_ctxt_free);
-       spin_unlock_bh(&xprt->sc_ctxt_lock);
+       kmem_cache_free(svc_rdma_ctxt_cachep, ctxt);
        atomic_dec(&xprt->sc_ctxt_used);
 }
 
@@ -461,40 +413,6 @@ static void sq_comp_handler(struct ib_cq *cq, void *cq_context)
        tasklet_schedule(&dto_tasklet);
 }
 
-static void create_context_cache(struct svcxprt_rdma *xprt,
-                                int ctxt_count, int ctxt_bump, int ctxt_max)
-{
-       struct svc_rdma_op_ctxt *ctxt;
-       int i;
-
-       xprt->sc_ctxt_max = ctxt_max;
-       xprt->sc_ctxt_bump = ctxt_bump;
-       xprt->sc_ctxt_cnt = 0;
-       atomic_set(&xprt->sc_ctxt_used, 0);
-
-       INIT_LIST_HEAD(&xprt->sc_ctxt_free);
-       for (i = 0; i < ctxt_count; i++) {
-               ctxt = kmalloc(sizeof(*ctxt), GFP_KERNEL);
-               if (ctxt) {
-                       INIT_LIST_HEAD(&ctxt->free_list);
-                       list_add(&ctxt->free_list, &xprt->sc_ctxt_free);
-                       xprt->sc_ctxt_cnt++;
-               }
-       }
-}
-
-static void destroy_context_cache(struct svcxprt_rdma *xprt)
-{
-       while (!list_empty(&xprt->sc_ctxt_free)) {
-               struct svc_rdma_op_ctxt *ctxt;
-               ctxt = list_entry(xprt->sc_ctxt_free.next,
-                                 struct svc_rdma_op_ctxt,
-                                 free_list);
-               list_del_init(&ctxt->free_list);
-               kfree(ctxt);
-       }
-}
-
 static struct svcxprt_rdma *rdma_create_xprt(struct svc_serv *serv,
                                             int listener)
 {
@@ -511,7 +429,6 @@ static struct svcxprt_rdma *rdma_create_xprt(struct svc_serv *serv,
 
        spin_lock_init(&cma_xprt->sc_lock);
        spin_lock_init(&cma_xprt->sc_read_complete_lock);
-       spin_lock_init(&cma_xprt->sc_ctxt_lock);
        spin_lock_init(&cma_xprt->sc_rq_dto_lock);
 
        cma_xprt->sc_ord = svcrdma_ord;
@@ -522,20 +439,7 @@ static struct svcxprt_rdma *rdma_create_xprt(struct svc_serv *serv,
        atomic_set(&cma_xprt->sc_sq_count, 0);
        atomic_set(&cma_xprt->sc_ctxt_used, 0);
 
-       if (!listener) {
-               int reqs = cma_xprt->sc_max_requests;
-               create_context_cache(cma_xprt,
-                                    reqs << 1, /* starting size */
-                                    reqs,      /* bump amount */
-                                    reqs +
-                                    cma_xprt->sc_sq_depth +
-                                    RPCRDMA_MAX_THREADS + 1); /* max */
-               if (list_empty(&cma_xprt->sc_ctxt_free)) {
-                       kfree(cma_xprt);
-                       return NULL;
-               }
-               clear_bit(XPT_LISTENER, &cma_xprt->sc_xprt.xpt_flags);
-       } else
+       if (listener)
                set_bit(XPT_LISTENER, &cma_xprt->sc_xprt.xpt_flags);
 
        return cma_xprt;
@@ -1077,7 +981,6 @@ static void __svc_rdma_free(struct work_struct *work)
        /* Destroy the CM ID */
        rdma_destroy_id(rdma->sc_cm_id);
 
-       destroy_context_cache(rdma);
        kfree(rdma);
 }