Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

xprtrdma: Decouple frwr_wp_create from frwr_map

frwr_wp_create is the only caller of frwr_map outside the encode
path. It registers a single 4-byte write-pad region from a stack-
local rpcrdma_mr_seg. Inlining the registration logic directly
(sg_init_table + sg_set_page + ib_dma_map_sg + ib_map_mr_sg +
IOVA mangle + reg_wr setup) eliminates the coupling that would
otherwise complicate the removal of rpcrdma_mr_seg from frwr_map's
interface.

The inlined version adds a proper error-unwind ladder: on failure,
the DMA mapping (if established) is released, ep->re_write_pad_mr is
cleared, and the MR is returned to the transport free list. The old
frwr_map-based code relied on rpcrdma_mrs_destroy at teardown to
reclaim partially-initialized MRs.

This is a one-time setup path; duplicating ~20 lines is a reasonable
tradeoff for decoupling the write-pad registration from the data-
path MR registration.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>

authored by

Chuck Lever and committed by
Trond Myklebust
6f2e565f 765bde47

+50 -7
+50 -7
net/sunrpc/xprtrdma/frwr_ops.c
··· 669 669 */ 670 670 int frwr_wp_create(struct rpcrdma_xprt *r_xprt) 671 671 { 672 + struct rpcrdma_buffer *buf = &r_xprt->rx_buf; 672 673 struct rpcrdma_ep *ep = r_xprt->rx_ep; 673 - struct rpcrdma_mr_seg seg; 674 + struct ib_reg_wr *reg_wr; 674 675 struct rpcrdma_mr *mr; 676 + struct ib_mr *ibmr; 677 + int dma_nents; 678 + int ret; 675 679 676 680 mr = rpcrdma_mr_get(r_xprt); 677 681 if (!mr) ··· 683 679 mr->mr_req = NULL; 684 680 ep->re_write_pad_mr = mr; 685 681 686 - seg.mr_len = XDR_UNIT; 687 - seg.mr_page = virt_to_page(ep->re_write_pad); 688 - seg.mr_offset = offset_in_page(ep->re_write_pad); 689 - if (IS_ERR(frwr_map(r_xprt, &seg, 1, true, xdr_zero, mr))) 690 - return -EIO; 682 + sg_init_table(mr->mr_sg, 1); 683 + sg_set_page(mr->mr_sg, virt_to_page(ep->re_write_pad), 684 + XDR_UNIT, offset_in_page(ep->re_write_pad)); 685 + 686 + mr->mr_dir = DMA_FROM_DEVICE; 687 + mr->mr_nents = 1; 688 + dma_nents = ib_dma_map_sg(ep->re_id->device, mr->mr_sg, 689 + mr->mr_nents, mr->mr_dir); 690 + if (!dma_nents) { 691 + ret = -EIO; 692 + goto out_mr; 693 + } 694 + mr->mr_device = ep->re_id->device; 695 + 696 + ibmr = mr->mr_ibmr; 697 + if (ib_map_mr_sg(ibmr, mr->mr_sg, dma_nents, NULL, 698 + PAGE_SIZE) != dma_nents) { 699 + ret = -EIO; 700 + goto out_unmap; 701 + } 702 + 703 + /* IOVA is not tagged with an XID; the write-pad is not RPC-specific. */ 704 + ib_update_fast_reg_key(ibmr, ib_inc_rkey(ibmr->rkey)); 705 + 706 + reg_wr = &mr->mr_regwr; 707 + reg_wr->mr = ibmr; 708 + reg_wr->key = ibmr->rkey; 709 + reg_wr->access = IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE; 710 + 711 + mr->mr_handle = ibmr->rkey; 712 + mr->mr_length = ibmr->length; 713 + mr->mr_offset = ibmr->iova; 714 + 691 715 trace_xprtrdma_mr_fastreg(mr); 692 716 693 717 mr->mr_cqe.done = frwr_wc_fastreg; ··· 725 693 mr->mr_regwr.wr.opcode = IB_WR_REG_MR; 726 694 mr->mr_regwr.wr.send_flags = 0; 727 695 728 - return ib_post_send(ep->re_id->qp, &mr->mr_regwr.wr, NULL); 696 + ret = ib_post_send(ep->re_id->qp, &mr->mr_regwr.wr, NULL); 697 + if (!ret) 698 + return 0; 699 + 700 + out_unmap: 701 + frwr_mr_unmap(mr); 702 + out_mr: 703 + ep->re_write_pad_mr = NULL; 704 + spin_lock(&buf->rb_lock); 705 + rpcrdma_mr_push(mr, &buf->rb_mrs); 706 + spin_unlock(&buf->rb_lock); 707 + return ret; 729 708 }