Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0bf48289 authored by Steve Wise's avatar Steve Wise Committed by J. Bruce Fields
Browse files

svcrdma: refactor marshalling logic



This patch refactors the NFSRDMA server marshalling logic to
remove the intermediary map structures.  It also fixes an existing bug
where the NFSRDMA server was not minding the device fast register page
list length limitations.

Signed-off-by: default avatarTom Tucker <tom@opengridcomputing.com>
Signed-off-by: default avatarSteve Wise <swise@opengridcomputing.com>
parent 1b19453d
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -115,14 +115,13 @@ struct svc_rdma_fastreg_mr {
	struct list_head frmr_list;
};
struct svc_rdma_req_map {
	struct svc_rdma_fastreg_mr *frmr;
	unsigned long count;
	union {
		struct kvec sge[RPCSVC_MAXPAGES];
		struct svc_rdma_chunk_sge ch[RPCSVC_MAXPAGES];
		unsigned long lkey[RPCSVC_MAXPAGES];
	};
};
#define RDMACTXT_F_FAST_UNREG	1
#define RDMACTXT_F_LAST_CTXT	2

#define	SVCRDMA_DEVCAP_FAST_REG		1	/* fast mr registration */
+273 −370

File changed.

Preview size limit exceeded, changes collapsed.

+22 −208

File changed.

Preview size limit exceeded, changes collapsed.

+36 −26
Original line number Diff line number Diff line
/*
 * Copyright (c) 2014 Open Grid Computing, Inc. All rights reserved.
 * Copyright (c) 2005-2007 Network Appliance, Inc. All rights reserved.
 *
 * This software is available to you under a choice of one of two
@@ -162,7 +163,6 @@ struct svc_rdma_req_map *svc_rdma_get_req_map(void)
		schedule_timeout_uninterruptible(msecs_to_jiffies(500));
	}
	map->count = 0;
	map->frmr = NULL;
	return map;
}

@@ -338,22 +338,21 @@ static void process_context(struct svcxprt_rdma *xprt,

	switch (ctxt->wr_op) {
	case IB_WR_SEND:
		if (test_bit(RDMACTXT_F_FAST_UNREG, &ctxt->flags))
			svc_rdma_put_frmr(xprt, ctxt->frmr);
		BUG_ON(ctxt->frmr);
		svc_rdma_put_context(ctxt, 1);
		break;

	case IB_WR_RDMA_WRITE:
		BUG_ON(ctxt->frmr);
		svc_rdma_put_context(ctxt, 0);
		break;

	case IB_WR_RDMA_READ:
	case IB_WR_RDMA_READ_WITH_INV:
		svc_rdma_put_frmr(xprt, ctxt->frmr);
		if (test_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags)) {
			struct svc_rdma_op_ctxt *read_hdr = ctxt->read_hdr;
			BUG_ON(!read_hdr);
			if (test_bit(RDMACTXT_F_FAST_UNREG, &ctxt->flags))
				svc_rdma_put_frmr(xprt, ctxt->frmr);
			spin_lock_bh(&xprt->sc_rq_dto_lock);
			set_bit(XPT_DATA, &xprt->sc_xprt.xpt_flags);
			list_add_tail(&read_hdr->dto_q,
@@ -365,6 +364,7 @@ static void process_context(struct svcxprt_rdma *xprt,
		break;

	default:
		BUG_ON(1);
		printk(KERN_ERR "svcrdma: unexpected completion type, "
		       "opcode=%d\n",
		       ctxt->wr_op);
@@ -380,30 +380,43 @@ static void process_context(struct svcxprt_rdma *xprt,
static void sq_cq_reap(struct svcxprt_rdma *xprt)
{
	struct svc_rdma_op_ctxt *ctxt = NULL;
	struct ib_wc wc;
	struct ib_wc wc_a[6];
	struct ib_wc *wc;
	struct ib_cq *cq = xprt->sc_sq_cq;
	int ret;

	memset(wc_a, 0, sizeof(wc_a));

	if (!test_and_clear_bit(RDMAXPRT_SQ_PENDING, &xprt->sc_flags))
		return;

	ib_req_notify_cq(xprt->sc_sq_cq, IB_CQ_NEXT_COMP);
	atomic_inc(&rdma_stat_sq_poll);
	while ((ret = ib_poll_cq(cq, 1, &wc)) > 0) {
		if (wc.status != IB_WC_SUCCESS)
	while ((ret = ib_poll_cq(cq, ARRAY_SIZE(wc_a), wc_a)) > 0) {
		int i;

		for (i = 0; i < ret; i++) {
			wc = &wc_a[i];
			if (wc->status != IB_WC_SUCCESS) {
				dprintk("svcrdma: sq wc err status %d\n",
					wc->status);

				/* Close the transport */
				set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags);
			}

			/* Decrement used SQ WR count */
			atomic_dec(&xprt->sc_sq_count);
			wake_up(&xprt->sc_send_wait);

		ctxt = (struct svc_rdma_op_ctxt *)(unsigned long)wc.wr_id;
			ctxt = (struct svc_rdma_op_ctxt *)
				(unsigned long)wc->wr_id;
			if (ctxt)
				process_context(xprt, ctxt);

			svc_xprt_put(&xprt->sc_xprt);
		}
	}

	if (ctxt)
		atomic_inc(&rdma_stat_sq_prod);
@@ -995,7 +1008,11 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
			need_dma_mr = 0;
		break;
	case RDMA_TRANSPORT_IB:
		if (!(devattr.device_cap_flags & IB_DEVICE_LOCAL_DMA_LKEY)) {
		if (!(newxprt->sc_dev_caps & SVCRDMA_DEVCAP_FAST_REG)) {
			need_dma_mr = 1;
			dma_mr_acc = IB_ACCESS_LOCAL_WRITE;
		} else if (!(devattr.device_cap_flags &
			     IB_DEVICE_LOCAL_DMA_LKEY)) {
			need_dma_mr = 1;
			dma_mr_acc = IB_ACCESS_LOCAL_WRITE;
		} else
@@ -1192,14 +1209,7 @@ static int svc_rdma_has_wspace(struct svc_xprt *xprt)
		container_of(xprt, struct svcxprt_rdma, sc_xprt);

	/*
	 * If there are fewer SQ WR available than required to send a
	 * simple response, return false.
	 */
	if ((rdma->sc_sq_depth - atomic_read(&rdma->sc_sq_count) < 3))
		return 0;

	/*
	 * ...or there are already waiters on the SQ,
	 * If there are already waiters on the SQ,
	 * return false.
	 */
	if (waitqueue_active(&rdma->sc_send_wait))