Skip to content

Commit

Permalink
svcrdma: Change WR context get/put to use the kmem cache
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Tom Tucker committed Jul 2, 2008
1 parent bf5927d commit 8948896
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 115 deletions.
6 changes: 0 additions & 6 deletions include/linux/sunrpc/svc_rdma.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
121 changes: 12 additions & 109 deletions net/sunrpc/xprtrdma/svc_rdma_transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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)
{
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down

0 comments on commit 8948896

Please sign in to comment.