net/rds/ib_frmr.c

Source file repositories/reference/linux-study-clean/net/rds/ib_frmr.c

File Facts

System
Linux kernel
Corpus path
net/rds/ib_frmr.c
Extension
.c
Size
12195 bytes
Lines
451
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

if (dma_addr & ~PAGE_MASK) {
			if (i > 0)
				goto out_unmap;
			else
				++frmr->dma_npages;
		}

		if ((dma_addr + dma_len) & ~PAGE_MASK) {
			if (i < ibmr->sg_dma_len - 1)
				goto out_unmap;
			else
				++frmr->dma_npages;
		}

		len += dma_len;
	}
	frmr->dma_npages += len >> PAGE_SHIFT;

	if (frmr->dma_npages > ibmr->pool->max_pages) {
		ret = -EMSGSIZE;
		goto out_unmap;
	}

	ret = rds_ib_post_reg_frmr(ibmr);
	if (ret)
		goto out_unmap;

	if (ibmr->pool->pool_type == RDS_IB_MR_8K_POOL)
		rds_ib_stats_inc(s_ib_rdma_mr_8k_used);
	else
		rds_ib_stats_inc(s_ib_rdma_mr_1m_used);

	return ret;

out_unmap:
	ib_dma_unmap_sg(rds_ibdev->dev, ibmr->sg, ibmr->sg_len,
			DMA_BIDIRECTIONAL);
	ibmr->sg_dma_len = 0;
	return ret;
}

static int rds_ib_post_inv(struct rds_ib_mr *ibmr)
{
	struct ib_send_wr *s_wr;
	struct rds_ib_frmr *frmr = &ibmr->u.frmr;
	struct rdma_cm_id *i_cm_id = ibmr->ic->i_cm_id;
	int ret = -EINVAL;

	if (!i_cm_id || !i_cm_id->qp || !frmr->mr)
		goto out;

	if (frmr->fr_state != FRMR_IS_INUSE)
		goto out;

	while (atomic_dec_return(&ibmr->ic->i_fastreg_wrs) <= 0) {
		atomic_inc(&ibmr->ic->i_fastreg_wrs);
		cpu_relax();
	}

	frmr->fr_inv = true;
	s_wr = &frmr->fr_wr;

	memset(s_wr, 0, sizeof(*s_wr));
	s_wr->wr_id = (unsigned long)(void *)ibmr;
	s_wr->opcode = IB_WR_LOCAL_INV;
	s_wr->ex.invalidate_rkey = frmr->mr->rkey;
	s_wr->send_flags = IB_SEND_SIGNALED;

	ret = ib_post_send(i_cm_id->qp, s_wr, NULL);
	if (unlikely(ret)) {
		rds_transition_frwr_state(ibmr, FRMR_IS_INUSE, FRMR_IS_STALE);
		frmr->fr_inv = false;
		/* enforce order of frmr->fr_inv update
		 * before incrementing i_fastreg_wrs
		 */
		smp_mb__before_atomic();
		atomic_inc(&ibmr->ic->i_fastreg_wrs);
		pr_err("RDS/IB: %s returned error(%d)\n", __func__, ret);
		goto out;
	}

	/* Wait for the FRMR_IS_FREE (or FRMR_IS_STALE) transition in order to
	 * 1) avoid a silly bouncing between "clean_list" and "drop_list"
	 *    triggered by function "rds_ib_reg_frmr" as it is releases frmr
	 *    regions whose state is not "FRMR_IS_FREE" right away.
	 * 2) prevents an invalid access error in a race
	 *    from a pending "IB_WR_LOCAL_INV" operation
	 *    with a teardown ("dma_unmap_sg", "put_page")
	 *    and de-registration ("ib_dereg_mr") of the corresponding
	 *    memory region.

Annotation

Implementation Notes