linux/net/sunrpc/xprtrdma/fmr_ops.c
/* Use the ib_map_phys_fmr() verb to register a memory region
 * for remote access via RDMA READ or RDMA WRITE.
 */
Use the ib_map_phys_fmr() verb to register a memory region
for remote access via RDMA READ or RDMA WRITE.
Use the ib_map_phys_fmr () verb to register a memory region for remote access via RDMA READ or RDMA WRITE .
static struct rpcrdma_mr_seg *
fmr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
	   int nsegs, bool writing, struct rpcrdma_mr **out)
{
	struct rpcrdma_mr_seg *seg1 = seg;
	int len, pageoff, i, rc;
	struct rpcrdma_mr *mr;
	u64 *dma_pages;
	mr = rpcrdma_mr_get(r_xprt);
	if (!mr)
		return ERR_PTR(-EAGAIN);
	pageoff = offset_in_page(seg1->mr_offset);
	seg1->mr_offset -= pageoff;	
	seg1->mr_len += pageoff;
	len = -pageoff;
	if (nsegs > RPCRDMA_MAX_FMR_SGES)
		nsegs = RPCRDMA_MAX_FMR_SGES;
	for (i = 0; i < nsegs;) {
		if (seg->mr_page)
			sg_set_page(&mr->mr_sg[i],
				    seg->mr_page,
				    seg->mr_len,
				    offset_in_page(seg->mr_offset));
		else
			sg_set_buf(&mr->mr_sg[i], seg->mr_offset,
				   seg->mr_len);
		len += seg->mr_len;
		++seg;
		++i;
		if ((i < nsegs && offset_in_page(seg->mr_offset)) ||
		    offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len))
			break;
	}
	mr->mr_dir = rpcrdma_data_dir(writing);
	mr->mr_nents = ib_dma_map_sg(r_xprt->rx_ia.ri_device,
				     mr->mr_sg, i, mr->mr_dir);
	if (!mr->mr_nents)
		goto out_dmamap_err;
	trace_xprtrdma_dma_map(mr);
	for (i = 0, dma_pages = mr->fmr.fm_physaddrs; i < mr->mr_nents; i++)
		dma_pages[i] = sg_dma_address(&mr->mr_sg[i]);
	rc = ib_map_phys_fmr(mr->fmr.fm_mr, dma_pages, mr->mr_nents,
			     dma_pages[0]);
	if (rc)
		goto out_maperr;
	mr->mr_handle = mr->fmr.fm_mr->rkey;
	mr->mr_length = len;
	mr->mr_offset = dma_pages[0] + pageoff;
	*out = mr;
	return seg;
out_dmamap_err:
	pr_err("rpcrdma: failed to DMA map sg %p sg_nents %d\n",
	       mr->mr_sg, i);
	rpcrdma_mr_put(mr);
	return ERR_PTR(-EIO);
out_maperr:
	pr_err("rpcrdma: ib_map_phys_fmr %u@0x%llx+%i (%d) status %i\n",
	       len, (unsigned long long)dma_pages[0],
	       pageoff, mr->mr_nents, rc);
	rpcrdma_mr_unmap_and_put(mr);
	return ERR_PTR(-EIO);
}
static struct rpcrdma_mr_seg * fmr_op_map ( struct rpcrdma_xprt * r_xprt , struct rpcrdma_mr_seg * seg , int nsegs , bool writing , struct rpcrdma_mr * * out ) { struct rpcrdma_mr_seg * seg1 = seg ; int len , pageoff , i , rc ; struct rpcrdma_mr * mr ; u64 * dma_pages ; mr = rpcrdma_mr_get ( r_xprt ) ; if ( ! mr ) return ERR_PTR ( - EAGAIN ) ; pageoff = offset_in_page ( seg1 -> mr_offset ) ; seg1 -> mr_offset -= pageoff ; seg1 -> mr_len += pageoff ; len = - pageoff ; if ( nsegs > RPCRDMA_MAX_FMR_SGES ) nsegs = RPCRDMA_MAX_FMR_SGES ; for ( i = 0 ; i < nsegs ; ) { if ( seg -> mr_page ) sg_set_page ( & mr -> mr_sg [ i ] , seg -> mr_page , seg -> mr_len , offset_in_page ( seg -> mr_offset ) ) ; else sg_set_buf ( & mr -> mr_sg [ i ] , seg -> mr_offset , seg -> mr_len ) ; len += seg -> mr_len ; ++ seg ; ++ i ; if ( ( i < nsegs && offset_in_page ( seg -> mr_offset ) ) || offset_in_page ( ( seg - 1 ) -> mr_offset + ( seg - 1 ) -> mr_len ) ) break ; } mr -> mr_dir = rpcrdma_data_dir ( writing ) ; mr -> mr_nents = ib_dma_map_sg ( r_xprt -> rx_ia . ri_device , mr -> mr_sg , i , mr -> mr_dir ) ; if ( ! mr -> mr_nents ) goto out_dmamap_err ; trace_xprtrdma_dma_map ( mr ) ; for ( i = 0 , dma_pages = mr -> fmr . fm_physaddrs ; i < mr -> mr_nents ; i ++ ) dma_pages [ i ] = sg_dma_address ( & mr -> mr_sg [ i ] ) ; rc = ib_map_phys_fmr ( mr -> fmr . fm_mr , dma_pages , mr -> mr_nents , dma_pages [ 0 ] ) ; if ( rc ) goto out_maperr ; mr -> mr_handle = mr -> fmr . fm_mr -> rkey ; mr -> mr_length = len ; mr -> mr_offset = dma_pages [ 0 ] + pageoff ; * out = mr ; return seg ; out_dmamap_err : pr_err ( " \n " , mr -> mr_sg , i ) ; rpcrdma_mr_put ( mr ) ; return ERR_PTR ( - EIO ) ; out_maperr : pr_err ( " \n " , len , ( unsigned long long ) dma_pages [ 0 ] , pageoff , mr -> mr_nents , rc ) ; rpcrdma_mr_unmap_and_put ( mr ) ; return ERR_PTR ( - EIO ) ; }
Use the ib_map_phys_fmr() verb to register a memory region
 for remote access via RDMA READ or RDMA WRITE.
Use the ib_map_phys_fmr () verb to register a memory region for remote access via RDMA READ or RDMA WRITE .
/* start of page */ /* Check for holes */