if (drop)
llist_add(&ibmr->llnode, &pool->drop_list); else
llist_add(&ibmr->llnode, &pool->free_list);
atomic_add(ibmr->sg_len, &pool->free_pinned);
atomic_inc(&pool->dirty_count);
/* If we've pinned too many pages, request a flush */ if (atomic_read(&pool->free_pinned) >= pool->max_free_pinned ||
atomic_read(&pool->dirty_count) >= pool->max_items / 5)
queue_delayed_work(rds_ib_mr_wq, &pool->flush_worker, 10);
}
staticint rds_ib_post_reg_frmr(struct rds_ib_mr *ibmr)
{ struct rds_ib_frmr *frmr = &ibmr->u.frmr; struct ib_reg_wr reg_wr; int ret, off = 0;
while (atomic_dec_return(&ibmr->ic->i_fastreg_wrs) <= 0) {
atomic_inc(&ibmr->ic->i_fastreg_wrs);
cpu_relax();
}
ret = ib_map_mr_sg_zbva(frmr->mr, ibmr->sg, ibmr->sg_dma_len,
&off, PAGE_SIZE); if (unlikely(ret != ibmr->sg_dma_len)) {
ret = ret < 0 ? ret : -EINVAL; goto out_inc;
}
if (cmpxchg(&frmr->fr_state, FRMR_IS_FREE, FRMR_IS_INUSE) != FRMR_IS_FREE) {
ret = -EBUSY; goto out_inc;
}
atomic_inc(&ibmr->ic->i_fastreg_inuse_count);
/* Perform a WR for the fast_reg_mr. Each individual page *inthesglistisaddedtothefastregpagelistandplaced *insidethefast_reg_mrWR.Thekeyusedisarolling8bit *counter,whichshouldguaranteeuniqueness.
*/
ib_update_fast_reg_key(frmr->mr, ibmr->remap_count++);
frmr->fr_reg = true;
ret = ib_post_send(ibmr->ic->i_cm_id->qp, ®_wr.wr, NULL); if (unlikely(ret)) { /* Failure here can be because of -ENOMEM as well */
rds_transition_frwr_state(ibmr, FRMR_IS_INUSE, FRMR_IS_STALE);
if (printk_ratelimit())
pr_warn("RDS/IB: %s returned error(%d)\n",
__func__, ret); goto out_inc;
}
/* Wait for the registration to complete in order to prevent an invalid *accesserrorresultingfromaracebetweenthememoryregionalready *beingaccessedwhileregistrationisstillpending.
*/
wait_event(frmr->fr_reg_done, !frmr->fr_reg);
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 *beforeincrementingi_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)avoidasillybouncingbetween"clean_list"and"drop_list" *triggeredbyfunction"rds_ib_reg_frmr"asitisreleasesfrmr *regionswhosestateisnot"FRMR_IS_FREE"rightaway. *2)preventsaninvalidaccesserrorinarace *fromapending"IB_WR_LOCAL_INV"operation *withateardown("dma_unmap_sg","put_page") *andde-registration("ib_dereg_mr")ofthecorresponding *memoryregion.
*/
wait_event(frmr->fr_inv_done, frmr->fr_state != FRMR_IS_INUSE);
/* String all ib_mr's onto one list and hand them to ib_unmap_fmr */
list_for_each_entry(ibmr, list, unmap_list) { if (ibmr->sg_dma_len) {
ret2 = rds_ib_post_inv(ibmr); if (ret2 && !ret)
ret = ret2;
}
}
if (ret)
pr_warn("RDS/IB: %s failed (err=%d)\n", __func__, ret);
/* Now we can destroy the DMA mapping and unpin any pages */
list_for_each_entry_safe(ibmr, next, list, unmap_list) {
*unpinned += ibmr->sg_len;
frmr = &ibmr->u.frmr;
__rds_ib_teardown_mr(ibmr); if (freed < goal || frmr->fr_state == FRMR_IS_STALE) { /* Don't de-allocate if the MR is not free yet */ if (frmr->fr_state == FRMR_IS_INUSE) continue;
if (ibmr->pool->pool_type == RDS_IB_MR_8K_POOL)
rds_ib_stats_inc(s_ib_rdma_mr_8k_free); else
rds_ib_stats_inc(s_ib_rdma_mr_1m_free);
list_del(&ibmr->unmap_list); if (frmr->mr)
ib_dereg_mr(frmr->mr);
kfree(ibmr);
freed++;
}
}
*nfreed = freed;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.