diff --git a/prov/efa/src/rdm/efa_rdm_ep_fiops.c b/prov/efa/src/rdm/efa_rdm_ep_fiops.c index eb30c5f3c56..1c24409aef6 100644 --- a/prov/efa/src/rdm/efa_rdm_ep_fiops.c +++ b/prov/efa/src/rdm/efa_rdm_ep_fiops.c @@ -468,6 +468,13 @@ void efa_rdm_ep_set_use_zcpy_rx(struct efa_rdm_ep *ep) goto out; } + /* FI_MR_LOCAL is not set, turn off zcpy recv */ + if (!ep->base_ep.domain->mr_local) { + EFA_INFO(FI_LOG_EP_CTRL, "FI_MR_LOCAL mode bit is not set, zero-copy receive protocol will be disabled\n"); + ep->use_zcpy_rx = false; + goto out; + } + if (ep->shm_ep) { EFA_INFO(FI_LOG_EP_CTRL, "Libfabric SHM is not turned off, zero-copy receive protocol will be disabled\n"); ep->use_zcpy_rx = false; diff --git a/prov/efa/src/rdm/efa_rdm_ep_utils.c b/prov/efa/src/rdm/efa_rdm_ep_utils.c index 6839f01675d..bf98cb08ef3 100644 --- a/prov/efa/src/rdm/efa_rdm_ep_utils.c +++ b/prov/efa/src/rdm/efa_rdm_ep_utils.c @@ -207,7 +207,7 @@ struct efa_rdm_ope *efa_rdm_ep_alloc_rxe(struct efa_rdm_ep *ep, fi_addr_t addr, */ int efa_rdm_ep_post_user_recv_buf(struct efa_rdm_ep *ep, struct efa_rdm_ope *rxe, size_t flags) { - struct efa_rdm_pke *pkt_entry; + struct efa_rdm_pke *pkt_entry = NULL; size_t rx_iov_offset = 0; int err, rx_iov_index = 0; @@ -225,10 +225,20 @@ int efa_rdm_ep_post_user_recv_buf(struct efa_rdm_ep *ep, struct efa_rdm_ope *rxe err = ofi_iov_locate(rxe->iov, rxe->iov_count, ep->msg_prefix_size, &rx_iov_index, &rx_iov_offset); if (OFI_UNLIKELY(err)) { EFA_WARN(FI_LOG_CQ, "ofi_iov_locate failure: %s (%d)\n", fi_strerror(-err), -err); - return err; + goto err_free; } + assert(rx_iov_index < rxe->iov_count); assert(rx_iov_offset < rxe->iov[rx_iov_index].iov_len); + assert(ep->base_ep.domain->mr_local); + + if (!rxe->desc[rx_iov_index]) { + err = -FI_EINVAL; + EFA_WARN(FI_LOG_EP_CTRL, + "No valid desc is provided, not complied with FI_MR_LOCAL: %s (%d)\n", + fi_strerror(-err), -err); + goto err_free; + } pkt_entry->payload = (char *) rxe->iov[rx_iov_index].iov_base + rx_iov_offset; pkt_entry->payload_mr = rxe->desc[rx_iov_index]; @@ -236,11 +246,10 @@ int efa_rdm_ep_post_user_recv_buf(struct efa_rdm_ep *ep, struct efa_rdm_ope *rxe err = efa_rdm_pke_recvv(&pkt_entry, 1); if (OFI_UNLIKELY(err)) { - efa_rdm_pke_release_rx(pkt_entry); EFA_WARN(FI_LOG_EP_CTRL, "failed to post user supplied buffer %d (%s)\n", -err, fi_strerror(-err)); - return err; + goto err_free; } #if ENABLE_DEBUG @@ -248,6 +257,11 @@ int efa_rdm_ep_post_user_recv_buf(struct efa_rdm_ep *ep, struct efa_rdm_ope *rxe #endif ep->user_rx_pkts_posted++; return 0; + +err_free: + if (pkt_entry) + efa_rdm_pke_release_rx(pkt_entry); + return err; } diff --git a/prov/efa/test/efa_unit_test_ep.c b/prov/efa/test/efa_unit_test_ep.c index 7dd99c63690..a1ae0d32aef 100644 --- a/prov/efa/test/efa_unit_test_ep.c +++ b/prov/efa/test/efa_unit_test_ep.c @@ -1066,6 +1066,22 @@ void test_efa_rdm_ep_user_p2p_not_supported_zcpy_rx_happy(struct efa_resource ** test_efa_rdm_ep_use_zcpy_rx_impl(resource, false, false, false); } +/** + * @brief Verify zcpy_rx is disabled if FI_MR_LOCAL is not set + */ +void test_efa_rdm_ep_user_zcpy_rx_unhappy_due_to_no_mr_local(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + + resource->hints = efa_unit_test_alloc_hints(FI_EP_RDM); + assert_non_null(resource->hints); + + resource->hints->caps = FI_MSG; + resource->hints->domain_attr->mr_mode &= ~FI_MR_LOCAL; + + test_efa_rdm_ep_use_zcpy_rx_impl(resource, false, true, false); +} + void test_efa_rdm_ep_close_discard_posted_recv(struct efa_resource **state) { struct efa_resource *resource = *state; diff --git a/prov/efa/test/efa_unit_tests.c b/prov/efa/test/efa_unit_tests.c index 828f1b32332..e37794b3e73 100644 --- a/prov/efa/test/efa_unit_tests.c +++ b/prov/efa/test/efa_unit_tests.c @@ -108,6 +108,7 @@ int main(void) cmocka_unit_test_setup_teardown(test_efa_rdm_ep_user_disable_p2p_zcpy_rx_happy, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), cmocka_unit_test_setup_teardown(test_efa_rdm_ep_user_zcpy_rx_unhappy_due_to_sas, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), cmocka_unit_test_setup_teardown(test_efa_rdm_ep_user_p2p_not_supported_zcpy_rx_happy, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_rdm_ep_user_zcpy_rx_unhappy_due_to_no_mr_local, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), cmocka_unit_test_setup_teardown(test_efa_rdm_ep_close_discard_posted_recv, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), cmocka_unit_test_setup_teardown(test_efa_rdm_ep_zcpy_recv_cancel, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), cmocka_unit_test_setup_teardown(test_efa_rdm_ep_post_handshake_error_handling_pke_exhaustion, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), diff --git a/prov/efa/test/efa_unit_tests.h b/prov/efa/test/efa_unit_tests.h index 9fbd0cd0e32..97121b6c9a9 100644 --- a/prov/efa/test/efa_unit_tests.h +++ b/prov/efa/test/efa_unit_tests.h @@ -118,6 +118,7 @@ void test_efa_rdm_ep_user_zcpy_rx_disabled(); void test_efa_rdm_ep_user_disable_p2p_zcpy_rx_happy(); void test_efa_rdm_ep_user_zcpy_rx_unhappy_due_to_sas(); void test_efa_rdm_ep_user_p2p_not_supported_zcpy_rx_happy(); +void test_efa_rdm_ep_user_zcpy_rx_unhappy_due_to_no_mr_local(); void test_efa_rdm_ep_close_discard_posted_recv(); void test_efa_rdm_ep_zcpy_recv_cancel(); void test_efa_rdm_ep_post_handshake_error_handling_pke_exhaustion();