From 9dafacce2e0c8fe053cf00ba30081488dc9a70a8 Mon Sep 17 00:00:00 2001 From: Amir Shehata Date: Wed, 5 Feb 2020 17:46:03 -0800 Subject: [PATCH] EX-773 lnet: RMDA infrastructure updates Add infrastructure to force RDMA for payloads < 4K. Add infrastructure to extract the first page in a payload. Useful for determining the type of the payload to be transmitted. Signed-off-by: Amir Shehata Change-Id: Id7dc26c83f00dadd26feca94fc4d8233872650d3 Reviewed-on: https://review.whamcloud.com/37453 Reviewed-by: Andreas Dilger Tested-by: jenkins Reviewed-by: Wang Shilong Tested-by: Maloo Reviewed-on: https://review.whamcloud.com/42000 Reviewed-by: Wang Shilong --- lnet/include/lnet/lib-lnet.h | 1 + lnet/include/lnet/lib-types.h | 2 ++ lnet/klnds/o2iblnd/o2iblnd_cb.c | 4 ++-- lnet/lnet/lib-md.c | 35 ++++++++++++++++++++++++++++------- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/lnet/include/lnet/lib-lnet.h b/lnet/include/lnet/lib-lnet.h index d245c11..19a4054 100644 --- a/lnet/include/lnet/lib-lnet.h +++ b/lnet/include/lnet/lib-lnet.h @@ -762,6 +762,7 @@ void lnet_me_unlink(struct lnet_me *me); void lnet_md_unlink(struct lnet_libmd *md); void lnet_md_deconstruct(struct lnet_libmd *lmd, struct lnet_event *ev); struct page *lnet_kvaddr_to_page(unsigned long vaddr); +struct page *lnet_get_first_page(struct lnet_libmd *md, unsigned int offset); int lnet_cpt_of_md(struct lnet_libmd *md, unsigned int offset); unsigned int lnet_get_lnd_timeout(void); diff --git a/lnet/include/lnet/lib-types.h b/lnet/include/lnet/lib-types.h index 9500550..ebdf14c 100644 --- a/lnet/include/lnet/lib-types.h +++ b/lnet/include/lnet/lib-types.h @@ -122,6 +122,8 @@ struct lnet_msg { enum lnet_msg_hstatus msg_health_status; /* This is a recovery message */ bool msg_recovery; + /* force an RDMA even if the message size is < 4K */ + bool msg_rdma_force; /* the number of times a transmission has been retried */ int msg_retry_count; /* flag to indicate that we do not want to resend this message */ diff --git a/lnet/klnds/o2iblnd/o2iblnd_cb.c b/lnet/klnds/o2iblnd/o2iblnd_cb.c index d6ccea1..c2249cf 100644 --- a/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -1655,7 +1655,7 @@ kiblnd_send(struct lnet_ni *ni, void *private, struct lnet_msg *lntmsg) /* is the REPLY message too small for RDMA? */ nob = offsetof(struct kib_msg, ibm_u.immediate.ibim_payload[lntmsg->msg_md->md_length]); - if (nob <= IBLND_MSG_SIZE) + if (nob <= IBLND_MSG_SIZE && !lntmsg->msg_rdma_force) break; /* send IMMEDIATE */ tx = kiblnd_get_idle_tx(ni, target.nid); @@ -1702,7 +1702,7 @@ kiblnd_send(struct lnet_ni *ni, void *private, struct lnet_msg *lntmsg) case LNET_MSG_PUT: /* Is the payload small enough not to need RDMA? */ nob = offsetof(struct kib_msg, ibm_u.immediate.ibim_payload[payload_nob]); - if (nob <= IBLND_MSG_SIZE) + if (nob <= IBLND_MSG_SIZE && !lntmsg->msg_rdma_force) break; /* send IMMEDIATE */ tx = kiblnd_get_idle_tx(ni, target.nid); diff --git a/lnet/lnet/lib-md.c b/lnet/lnet/lib-md.c index dfb8b03..e56db19 100644 --- a/lnet/lnet/lib-md.c +++ b/lnet/lnet/lib-md.c @@ -105,10 +105,9 @@ lnet_kvaddr_to_page(unsigned long vaddr) } EXPORT_SYMBOL(lnet_kvaddr_to_page); -int -lnet_cpt_of_md(struct lnet_libmd *md, unsigned int offset) +struct page * +lnet_get_first_page(struct lnet_libmd *md, unsigned int offset) { - int cpt = CFS_CPT_ANY; unsigned int niov; struct bio_vec *kiov; @@ -121,23 +120,45 @@ lnet_cpt_of_md(struct lnet_libmd *md, unsigned int offset) md = lnet_handle2md(&md->md_bulk_handle); if (!md || md->md_niov == 0) - return CFS_CPT_ANY; + return NULL; kiov = md->md_kiov; niov = md->md_niov; + /* + * The offset provided can be within the first iov/kiov entry or + * it could go beyond it. In that case we need to make sure to + * look at the page which actually contains the data that will be + * DMAed. + */ while (offset >= kiov->bv_len) { offset -= kiov->bv_len; niov--; kiov++; if (niov == 0) { CERROR("offset %d goes beyond kiov\n", offset); - goto out; + return NULL; } } - cpt = cfs_cpt_of_node(lnet_cpt_table(), - page_to_nid(kiov->bv_page)); + return kiov->bv_page; +} + +int +lnet_cpt_of_md(struct lnet_libmd *md, unsigned int offset) +{ + struct page *page; + int cpt = CFS_CPT_ANY; + + page = lnet_get_first_page(md, offset); + if (!page) { + CDEBUG(D_NET, "Couldn't resolve first page of md %p with offset %u\n", + md, offset); + goto out; + } + + cpt = cfs_cpt_of_node(lnet_cpt_table(), page_to_nid(page)); + out: return cpt; } -- 1.8.3.1