All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] Registering non-contiguous memory
@ 2017-02-05 16:46 Alex Margolin
       [not found] ` <VI1PR05MB127817A311C332553E4391AFB9410-79XLn2atqDMOK6E67s+DINqRiQSDpxhJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
  0 siblings, 1 reply; 12+ messages in thread
From: Alex Margolin @ 2017-02-05 16:46 UTC (permalink / raw)
  To: linux-rdma-u79uwXL29TY76Z2rM5mHXA

Introduction
--------------------------------------------------------------------------------
Numerous applications communicate buffers with a non-contiguous memory layout.
For example, HPC applications often work on a matrix, and require sending a row or a column. Sending non-contiguous data requires specifying all the buffers being transferred, along with potentially the same amount of memory keys (should the buffers be registered under different memory regions). Extended memory windows are proposed to address complex memory layouts, and allow the user to send and receive them in an efficient manner.
This RFC proposes an extension for memory windows for the use of non-contiguous buffers.

The problem
--------------------------------------------------------------------------------
Currently, this is implemented using "sge_list" with an entry for each buffer, but sending a regular structure may cause a multitude of entries - which can easily be represented in a more compact way. For example, a matrix column:
               M
          -----------
         | |X| | | | |
          -----------
         | |X| | | | |
          -----------   N
         | |X| | | | |
          -----------
         | |X| | | | |
          -----------

In the current implementation, sending such a column would require N scatter- gather entries, each with the same length and within equal distance from the previous one.

A similar case is data spanning across multiple memory regions:



                     ----------
                    |          |
                    |          |
                    | Memory   |
                   /| region #1|
     "Composite   / |          |
       region"   /  |          |
     ---------- /  -|          |
    |          |  / |          |
    |          | /   ----------
     ---------- <
    |          | \   ---------- 
    |          |  --|          |
    |          |    | Memory   |
    |          | ___| region #2|
     ---------- <   |          |
    |          | \   ----------
     ----------\  \_ ----------
                \   |          |
                 \  | Memory   |
                  \-| region #N|
                    |          |
                    |          |
                     ----------

Currently, sending such a "composite region" involves specifying all N regions it spans across. 

The problem is that a large amount of information needs to be passed with the WR to communicate a potentially small amount of data, causing significant overhead.
This is especially true if the layout information does not fit in a single WR
(inline) and extra overhead is incurred. Also, applications tend to re-use the same layout over a multitude of network operations, thus aggravating this problem.

Potentially, one may want to use more than one dimension of stride, like the case of a side of a multi-dimensional cube (M * N * O):

                              O
                          ___ ___ ___
                        /_X_/_X_/_X_/|
                    N  /_X_/_X_/_X_/||
                      /_X_/_X_/_X /|/|
                     |   |   |   | /||
                     |___|___|___|/|/|
                  M  |   |   |   | /||
                     |___|___|___|/|/
                     |   |   |   | /
                     |___|___|___|/

Suggested Solution
--------------------------------------------------------------------------------
The suggested solution is to extend the existing API of memory windows to allow the user to describe a memory layout: a compact description of patterns of memory - which can later be used to transfer buffers according to them.

For the aforementioned matrix example - the layout will include the size of a single cell in the matrix, the distance between cells (M times that size) and the total amount of buffers (N). For the composite example, the layout will simply contain the list of memory regions along with a base-pointer and length.

Suggested API Details
--------------------------------------------------------------------------------
The main addition is the layout structure, composed of an array of entries.
Each entry refers to a previously created memory region or memory window, which allows the formation of multi-level memory windows for complex structures.
Each entry can be a contiguous area, creating a composite, or a quantity of equally-distanced buffers (but not a mixture of the two). The dimension of the strides is accommodated by an variable-length array of item counts and stride interval sizes. An additional per-entry field enables non-uniform interleaving, where the ratio is not 1:1, so we may take two items from the first entry for each item of the second entry.

The layout is "switched on" as a bind parameter with an additional access flag, which is somewhat of a misuse, but since struct ibv_mw_bind_info is not easily expandable in the functions using it, the alternative is an additional verb.

We do propose adding a verb for the allocation of such memory windows, which is required since the original memory window allocation function is not easily extendable, and we require an additional parameter to determine the amount of resources to allocate towards it (descriptors). In addition, this number is available for existing windows, in order to determine how to set this for a composite of two existing windows, or to keep track of resource use for it.

Finally, we add the option to obtain a local memory key for memory windows, aside from the currently available remote key. This can be specified in an SGE to send data out of a memory layout. This key will only be valid if local access is requested in the access flags.



Signed-off-by: Alex Margolin <alexma@xxxxxxxxxxxx>
---
diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h index ea3dade..9ef3639 100644
--- a/include/infiniband/driver.h
+++ b/include/infiniband/driver.h
@@ -96,6 +96,20 @@ struct verbs_qp {
 	uint32_t		comp_mask;
 	struct verbs_xrcd       *xrcd;
 };
+
+enum verbs_mw_mask {
+	VERBS_MW_LKEY		= 1 << 0,
+	VERBS_MW_DESCRIPTOR_NUM	= 1 << 1,
+	VERBS_MW_RESERVED	= 1 << 2
+};
+
+struct verbs_mw {
+	struct ibv_mw		mw;
+	uint32_t		comp_mask;
+	uint32_t		lkey;
+	uint32_t		descriptor_num;
+};
+
 typedef struct ibv_device *(*ibv_driver_init_func)(const char *uverbs_sys_path,
 						   int abi_version);
 typedef struct verbs_device *(*verbs_driver_init_func)(const char *uverbs_sys_path, diff --git a/include/infiniband/verbs.h b/include/infiniband/verbs.h index e994c21..748dc60 100644
--- a/include/infiniband/verbs.h
+++ b/include/infiniband/verbs.h
@@ -214,6 +214,23 @@ struct ibv_tso_caps {
 	uint32_t supported_qpts;
 };
 
+struct ibv_ncm_caps {
+	uint64_t general_caps;
+	uint32_t max_mkey_ims_list_size;
+	uint32_t max_send_wqe_inline_cms;
+	uint32_t max_send_wqe_inline_ims;
+	uint32_t max_mw_recursion_depth;
+	uint32_t max_mw_stride_dimenson;
+};
+
+enum ibv_ncm_general_caps {
+	IBV_NCM_SUPPORT_COMPOSITE = 1 << 0,
+	IBV_NCM_SUPPORT_INTERLEAVED = 1 << 1,
+	IBV_NCM_SUPPORT_INTERLEAVED_REPETITION = 1 << 2,
+	IBV_NCM_SUPPORT_INTERLEAVED_NONUNIFORM_REPETITION = 1 << 3,
+	IBV_NCM_SUPPORT_INTERLEAVED_NONUNIFORM_TOTAL_ITEMS = 1 << 4, };
+
 /* RX Hash function flags */
 enum ibv_rx_hash_function_flags {
 	IBV_RX_HASH_FUNC_TOEPLITZ	= 1 << 0,
@@ -256,6 +273,7 @@ struct ibv_device_attr_ex {
 	struct ibv_tso_caps	tso_caps;
 	struct ibv_rss_caps     rss_caps;
 	uint32_t		max_wq_type_rq;
+	struct ibv_ncm_caps     ncm_caps;
 };
 
 enum ibv_mtu {
@@ -472,13 +490,7 @@ enum ibv_access_flags {
 	IBV_ACCESS_MW_BIND		= (1<<4),
 	IBV_ACCESS_ZERO_BASED		= (1<<5),
 	IBV_ACCESS_ON_DEMAND		= (1<<6),
-};
-
-struct ibv_mw_bind_info {
-	struct ibv_mr	*mr;
-	uint64_t	 addr;
-	uint64_t	 length;
-	int		 mw_access_flags; /* use ibv_access_flags */
+	IBV_ACCESS_BIND_MW_NONCONTIG	= (1<<7),
 };
 
 struct ibv_pd {
@@ -533,6 +545,61 @@ struct ibv_mw {
 	enum ibv_mw_type	type;
 };
 
+struct ibv_mw_alloc_attr_ex {
+	unit32_t comp_mask;
+	struct ibv_pd *pd;
+	enum ibv_mw_type type;
+	int max_descriptors;
+};
+
+enum ibv_mw_entry_type {
+	IBV_MW_ENTRY_USE_MR = 0,
+	IBV_MW_ENTRY_USE_MW
+};
+
+struct ibv_mw_bind_layout_entry {
+	uint32_t comp_mask;
+	enum ibv_mw_entry_type mem_obj_type;
+	union mem_obj {
+		struct ibv_mr *mr;
+		struct ibv_mw *mw;
+	};
+	uint64_t addr;
+	uint64_t length;
+	struct {
+		uint64_t repeat_count;
+		uint32_t dimension_count;
+		struct {
+			uint64_t stride;
+			uint64_t count;
+		} *dimension;
+	} interleaved;
+};
+
+enum ibv_mw_bind_layout_type {
+	IBV_MW_BIND_LAYOUT_TYPE_COMPOSITE = 0,
+	IBV_MW_BIND_LAYOUT_TYPE_INTERLEAVED
+};
+
+struct ibv_mw_bind_layout {
+	uint32_t comp_mask;
+	enum ibv_mw_bind_layout_type type;
+	uint32_t entry_count;
+	struct ibv_mw_bind_info_entry *entries; };
+
+struct ibv_mw_bind_info {
+	union {
+		struct {
+			struct ibv_mr   *mr;
+			uint64_t        addr;
+			uint64_t        length;
+		};
+		struct ibv_mw_bind_layout *layout;
+	};
+	int		 mw_access_flags; /* use ibv_access_flags */
+};
+
 struct ibv_global_route {
 	union ibv_gid		dgid;
 	uint32_t		flow_label;
@@ -1411,11 +1478,13 @@ enum verbs_context_mask {
 	VERBS_CONTEXT_QP	= 1 << 2,
 	VERBS_CONTEXT_CREATE_FLOW = 1 << 3,
 	VERBS_CONTEXT_DESTROY_FLOW = 1 << 4,
-	VERBS_CONTEXT_RESERVED	= 1 << 5
+	VERBS_CONTEXT_ALLOC_MW	= 1 << 5,
+	VERBS_CONTEXT_RESERVED	= 1 << 6
 };
 
 struct verbs_context {
 	/*  "grows up" - new fields go here */
+	struct ib_mw * (*alloc_mw_ex)(struct ibv_mw_alloc_attr 
+*mw_alloc_attr);
 	int (*destroy_rwq_ind_table)(struct ibv_rwq_ind_table *rwq_ind_table);
 	struct ibv_rwq_ind_table *(*create_rwq_ind_table)(struct ibv_context *context,
 							  struct ibv_rwq_ind_table_init_attr *init_attr);
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC] Registering non-contiguous memory
       [not found] ` <VI1PR05MB127817A311C332553E4391AFB9410-79XLn2atqDMOK6E67s+DINqRiQSDpxhJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
@ 2017-02-05 22:44   ` Jason Gunthorpe
       [not found]     ` <20170205224401.GB26474-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
  2017-02-28 12:31   ` Tom Talpey
  2017-11-01 11:11   ` Alex Margolin
  2 siblings, 1 reply; 12+ messages in thread
From: Jason Gunthorpe @ 2017-02-05 22:44 UTC (permalink / raw)
  To: Alex Margolin; +Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA

On Sun, Feb 05, 2017 at 04:46:04PM +0000, Alex Margolin wrote:

> +struct verbs_mw {
> +	struct ibv_mw		mw;
> +	uint32_t		comp_mask;
> +	uint32_t		lkey;
> +	uint32_t		descriptor_num;
> +};

Just as a general comment for all future patches - now that the
provider interface is private I don't want to see 'comp_mask' stuff in
driver.h


> @@ -1411,11 +1478,13 @@ enum verbs_context_mask {
>  	VERBS_CONTEXT_QP	= 1 << 2,
>  	VERBS_CONTEXT_CREATE_FLOW = 1 << 3,
>  	VERBS_CONTEXT_DESTROY_FLOW = 1 << 4,
> -	VERBS_CONTEXT_RESERVED	= 1 << 5
> +	VERBS_CONTEXT_ALLOC_MW	= 1 << 5,
> +	VERBS_CONTEXT_RESERVED	= 1 << 6
>  };

What is this reserved thing?

Don't forget man pages are required.

Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC] Registering non-contiguous memory
       [not found] ` <VI1PR05MB127817A311C332553E4391AFB9410-79XLn2atqDMOK6E67s+DINqRiQSDpxhJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
  2017-02-05 22:44   ` Jason Gunthorpe
@ 2017-02-28 12:31   ` Tom Talpey
       [not found]     ` <f40f326d-e76b-0471-dc7d-e81b7d07db78-CLs1Zie5N5HQT0dZR+AlfA@public.gmane.org>
  2017-11-01 11:11   ` Alex Margolin
  2 siblings, 1 reply; 12+ messages in thread
From: Tom Talpey @ 2017-02-28 12:31 UTC (permalink / raw)
  To: Alex Margolin, linux-rdma-u79uwXL29TY76Z2rM5mHXA

On 2/5/2017 11:46 AM, Alex Margolin wrote:
> Introduction
> --------------------------------------------------------------------------------
> Numerous applications communicate buffers with a non-contiguous memory layout.
> For example, HPC applications often work on a matrix, and require sending a row or a column. Sending non-contiguous data requires specifying all the buffers being transferred, along with potentially the same amount of memory keys (should the buffers be registered under different memory regions). Extended memory windows are proposed to address complex memory layouts, and allow the user to send and receive them in an efficient manner.
> This RFC proposes an extension for memory windows for the use of non-contiguous buffers.
>
...
> The layout is "switched on" as a bind parameter with an additional access flag, which is somewhat of a misuse, but since struct ibv_mw_bind_info is not easily expandable in the functions using it, the alternative is an additional verb.
>
> We do propose adding a verb for the allocation of such memory windows, which is required since the original memory window allocation function is not easily extendable, and we require an additional parameter to determine the amount of resources to allocate towards it (descriptors). In addition, this number is available for existing windows, in order to determine how to set this for a composite of two existing windows, or to keep track of resource use for it.
>
> Finally, we add the option to obtain a local memory key for memory windows, aside from the currently available remote key. This can be specified in an SGE to send data out of a memory layout. This key will only be valid if local access is requested in the access flags.

How does the application detect whether the adapter supports this new
verb? I don't see an attribute or other bit exposing it above the API.

Also, what applications are likely to use it? It is my understanding
that relatively few applications use Memory Windows-style registration
today. Roughly what performance benefit do you expect they will achieve
from the region descriptor format overall, motivating them to change?

Tom.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [RFC] Registering non-contiguous memory
       [not found]     ` <f40f326d-e76b-0471-dc7d-e81b7d07db78-CLs1Zie5N5HQT0dZR+AlfA@public.gmane.org>
@ 2017-03-16 13:32       ` Alex Margolin
  0 siblings, 0 replies; 12+ messages in thread
From: Alex Margolin @ 2017-03-16 13:32 UTC (permalink / raw)
  To: Tom Talpey, linux-rdma-u79uwXL29TY76Z2rM5mHXA



> -----Original Message-----
> From: Tom Talpey [mailto:tom-CLs1Zie5N5HQT0dZR+AlfA@public.gmane.org]
> Sent: Tuesday, February 28, 2017 2:31 PM
> To: Alex Margolin <alexma-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>; linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Subject: Re: [RFC] Registering non-contiguous memory
> 
> On 2/5/2017 11:46 AM, Alex Margolin wrote:
> > Introduction
> > ----------------------------------------------------------------------
> > ---------- Numerous applications communicate buffers with a
> > non-contiguous memory layout.
> > For example, HPC applications often work on a matrix, and require
> sending a row or a column. Sending non-contiguous data requires
> specifying all the buffers being transferred, along with potentially the
> same amount of memory keys (should the buffers be registered under
> different memory regions). Extended memory windows are proposed to
> address complex memory layouts, and allow the user to send and receive
> them in an efficient manner.
> > This RFC proposes an extension for memory windows for the use of non-
> contiguous buffers.
> >
> ...
> > The layout is "switched on" as a bind parameter with an additional
> access flag, which is somewhat of a misuse, but since struct
> ibv_mw_bind_info is not easily expandable in the functions using it, the
> alternative is an additional verb.
> >
> > We do propose adding a verb for the allocation of such memory windows,
> which is required since the original memory window allocation function
> is not easily extendable, and we require an additional parameter to
> determine the amount of resources to allocate towards it (descriptors).
> In addition, this number is available for existing windows, in order to
> determine how to set this for a composite of two existing windows, or to
> keep track of resource use for it.
> >
> > Finally, we add the option to obtain a local memory key for memory
> windows, aside from the currently available remote key. This can be
> specified in an SGE to send data out of a memory layout. This key will
> only be valid if local access is requested in the access flags.
> 
> How does the application detect whether the adapter supports this new
> verb? I don't see an attribute or other bit exposing it above the API.

The proposed alloc_mw_ex() will be detected with VERBS_CONTEXT_ALLOC_MW in enum verbs_context_mask.
It will only make sense to call this verb if the feature is enabled in struct ibv_ncm_caps.

> 
> Also, what applications are likely to use it? It is my understanding
> that relatively few applications use Memory Windows-style registration
> today. Roughly what performance benefit do you expect they will achieve
> from the region descriptor format overall, motivating them to change?

The target applications are not necessarily the ones already using the existing memory windows. Applications which do matrix operations (e.g. multiplication) or use non-contiguous datatypes (with MPI, for example) are good candidates. 
The performance benefit comes from passing the layout to the NIC once, then only sending the base pointer for each send. In the case of a column in an NxN matrix - each send will only give the pointer to the first element (and the memory window) instead of an sge_list of size N. Similarly, a non-contiguous datatype layout will be passed to the NIC only once.

> 
> Tom.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [RFC] Registering non-contiguous memory
       [not found]     ` <20170205224401.GB26474-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
@ 2017-03-23 18:21       ` Alex Margolin
       [not found]         ` <DB5PR05MB12702D1DE9A7E7773FF823ACB93F0-8IvNv+8VlcCeKfjjHlISstqRiQSDpxhJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
  0 siblings, 1 reply; 12+ messages in thread
From: Alex Margolin @ 2017-03-23 18:21 UTC (permalink / raw)
  To: Jason Gunthorpe; +Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA



> -----Original Message-----
> From: Jason Gunthorpe [mailto:jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org]
> Sent: Monday, February 06, 2017 12:44 AM
> To: Alex Margolin <alexma-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Subject: Re: [RFC] Registering non-contiguous memory
> 
> On Sun, Feb 05, 2017 at 04:46:04PM +0000, Alex Margolin wrote:
> 
> > +struct verbs_mw {
> > +	struct ibv_mw		mw;
> > +	uint32_t		comp_mask;
> > +	uint32_t		lkey;
> > +	uint32_t		descriptor_num;
> > +};
> 
> Just as a general comment for all future patches - now that the provider
> interface is private I don't want to see 'comp_mask' stuff in driver.h

How else would we support future extensibility otherwise? It seems that all the other structs in driver.h have comp_mask: struct verbs_xrcd, struct verbs_srq and struct verbs_qp.

> 
> 
> > @@ -1411,11 +1478,13 @@ enum verbs_context_mask {
> >  	VERBS_CONTEXT_QP	= 1 << 2,
> >  	VERBS_CONTEXT_CREATE_FLOW = 1 << 3,
> >  	VERBS_CONTEXT_DESTROY_FLOW = 1 << 4,
> > -	VERBS_CONTEXT_RESERVED	= 1 << 5
> > +	VERBS_CONTEXT_ALLOC_MW	= 1 << 5,
> > +	VERBS_CONTEXT_RESERVED	= 1 << 6
> >  };
> 
> What is this reserved thing?

Note that this reserved bit was there before the patch... I just left it there.

> 
> Don't forget man pages are required.
> 
> Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC] Registering non-contiguous memory
       [not found]         ` <DB5PR05MB12702D1DE9A7E7773FF823ACB93F0-8IvNv+8VlcCeKfjjHlISstqRiQSDpxhJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
@ 2017-03-23 18:40           ` Jason Gunthorpe
  0 siblings, 0 replies; 12+ messages in thread
From: Jason Gunthorpe @ 2017-03-23 18:40 UTC (permalink / raw)
  To: Alex Margolin; +Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA

On Thu, Mar 23, 2017 at 06:21:09PM +0000, Alex Margolin wrote:
> 
> 
> > From: Jason Gunthorpe [mailto:jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org]
> > Sent: Monday, February 06, 2017 12:44 AM
> > To: Alex Margolin <alexma-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> > Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> > Subject: Re: [RFC] Registering non-contiguous memory
> > 
> > On Sun, Feb 05, 2017 at 04:46:04PM +0000, Alex Margolin wrote:
> > 
> > > +struct verbs_mw {
> > > +	struct ibv_mw		mw;
> > > +	uint32_t		comp_mask;
> > > +	uint32_t		lkey;
> > > +	uint32_t		descriptor_num;
> > > +};
> > 
> > Just as a general comment for all future patches - now that the provider
> > interface is private I don't want to see 'comp_mask' stuff in driver.h
> 
> How else would we support future extensibility otherwise? It seems
> that all the other structs in driver.h have comp_mask: struct
> verbs_xrcd, struct verbs_srq and struct verbs_qp.

comp_mask was originaly to support ABI change, but the driver ABI is
now private so we do not need it in driver.h. If you need optional
things then a 'flags' or a NULL value is the way to go.

It is hard to understand what you are proposing here since verbs_mw
wasn't even used in the patch.

Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [RFC] Registering non-contiguous memory
       [not found] ` <VI1PR05MB127817A311C332553E4391AFB9410-79XLn2atqDMOK6E67s+DINqRiQSDpxhJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
  2017-02-05 22:44   ` Jason Gunthorpe
  2017-02-28 12:31   ` Tom Talpey
@ 2017-11-01 11:11   ` Alex Margolin
       [not found]     ` <DB5PR05MB1270529922F451A2CACF7AE9B95F0-8IvNv+8VlcCeKfjjHlISstqRiQSDpxhJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
  2 siblings, 1 reply; 12+ messages in thread
From: Alex Margolin @ 2017-11-01 11:11 UTC (permalink / raw)
  To: 'linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org'

We're planning to start the implementation soon - now is the last opportunity for input before we do.
Please let us know of any comments or suggestions you have.

-----Original Message-----
From: Alex Margolin 
Sent: Sunday, February 05, 2017 6:46 PM
To: linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: [RFC] Registering non-contiguous memory

Introduction
--------------------------------------------------------------------------------
Numerous applications communicate buffers with a non-contiguous memory layout.
For example, HPC applications often work on a matrix, and require sending a row or a column. Sending non-contiguous data requires specifying all the buffers being transferred, along with potentially the same amount of memory keys (should the buffers be registered under different memory regions). Extended memory windows are proposed to address complex memory layouts, and allow the user to send and receive them in an efficient manner.
This RFC proposes an extension for memory windows for the use of non-contiguous buffers.

The problem
--------------------------------------------------------------------------------
Currently, this is implemented using "sge_list" with an entry for each buffer, but sending a regular structure may cause a multitude of entries - which can easily be represented in a more compact way. For example, a matrix column:
               M
          -----------
         | |X| | | | |
          -----------
         | |X| | | | |
          -----------   N
         | |X| | | | |
          -----------
         | |X| | | | |
          -----------

In the current implementation, sending such a column would require N scatter- gather entries, each with the same length and within equal distance from the previous one.

A similar case is data spanning across multiple memory regions:



                     ----------
                    |          |
                    |          |
                    | Memory   |
                   /| region #1|
     "Composite   / |          |
       region"   /  |          |
     ---------- /  -|          |
    |          |  / |          |
    |          | /   ----------
     ---------- <
    |          | \   ---------- 
    |          |  --|          |
    |          |    | Memory   |
    |          | ___| region #2|
     ---------- <   |          |
    |          | \   ----------
     ----------\  \_ ----------
                \   |          |
                 \  | Memory   |
                  \-| region #N|
                    |          |
                    |          |
                     ----------

Currently, sending such a "composite region" involves specifying all N regions it spans across. 

The problem is that a large amount of information needs to be passed with the WR to communicate a potentially small amount of data, causing significant overhead.
This is especially true if the layout information does not fit in a single WR
(inline) and extra overhead is incurred. Also, applications tend to re-use the same layout over a multitude of network operations, thus aggravating this problem.

Potentially, one may want to use more than one dimension of stride, like the case of a side of a multi-dimensional cube (M * N * O):

                              O
                          ___ ___ ___
                        /_X_/_X_/_X_/|
                    N  /_X_/_X_/_X_/||
                      /_X_/_X_/_X /|/|
                     |   |   |   | /||
                     |___|___|___|/|/|
                  M  |   |   |   | /||
                     |___|___|___|/|/
                     |   |   |   | /
                     |___|___|___|/

Suggested Solution
--------------------------------------------------------------------------------
The suggested solution is to extend the existing API of memory windows to allow the user to describe a memory layout: a compact description of patterns of memory - which can later be used to transfer buffers according to them.

For the aforementioned matrix example - the layout will include the size of a single cell in the matrix, the distance between cells (M times that size) and the total amount of buffers (N). For the composite example, the layout will simply contain the list of memory regions along with a base-pointer and length.

Suggested API Details
--------------------------------------------------------------------------------
The main addition is the layout structure, composed of an array of entries.
Each entry refers to a previously created memory region or memory window, which allows the formation of multi-level memory windows for complex structures.
Each entry can be a contiguous area, creating a composite, or a quantity of equally-distanced buffers (but not a mixture of the two). The dimension of the strides is accommodated by an variable-length array of item counts and stride interval sizes. An additional per-entry field enables non-uniform interleaving, where the ratio is not 1:1, so we may take two items from the first entry for each item of the second entry.

The layout is "switched on" as a bind parameter with an additional access flag, which is somewhat of a misuse, but since struct ibv_mw_bind_info is not easily expandable in the functions using it, the alternative is an additional verb.

We do propose adding a verb for the allocation of such memory windows, which is required since the original memory window allocation function is not easily extendable, and we require an additional parameter to determine the amount of resources to allocate towards it (descriptors). In addition, this number is available for existing windows, in order to determine how to set this for a composite of two existing windows, or to keep track of resource use for it.

Finally, we add the option to obtain a local memory key for memory windows, aside from the currently available remote key. This can be specified in an SGE to send data out of a memory layout. This key will only be valid if local access is requested in the access flags.



Signed-off-by: Alex Margolin <alexma@xxxxxxxxxxxx>
---
diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h index ea3dade..9ef3639 100644
--- a/include/infiniband/driver.h
+++ b/include/infiniband/driver.h
@@ -96,6 +96,20 @@ struct verbs_qp {
 	uint32_t		comp_mask;
 	struct verbs_xrcd       *xrcd;
 };
+
+enum verbs_mw_mask {
+	VERBS_MW_LKEY		= 1 << 0,
+	VERBS_MW_DESCRIPTOR_NUM	= 1 << 1,
+	VERBS_MW_RESERVED	= 1 << 2
+};
+
+struct verbs_mw {
+	struct ibv_mw		mw;
+	uint32_t		comp_mask;
+	uint32_t		lkey;
+	uint32_t		descriptor_num;
+};
+
 typedef struct ibv_device *(*ibv_driver_init_func)(const char *uverbs_sys_path,
 						   int abi_version);
 typedef struct verbs_device *(*verbs_driver_init_func)(const char *uverbs_sys_path, diff --git a/include/infiniband/verbs.h b/include/infiniband/verbs.h index e994c21..748dc60 100644
--- a/include/infiniband/verbs.h
+++ b/include/infiniband/verbs.h
@@ -214,6 +214,23 @@ struct ibv_tso_caps {
 	uint32_t supported_qpts;
 };
 
+struct ibv_ncm_caps {
+	uint64_t general_caps;
+	uint32_t max_mkey_ims_list_size;
+	uint32_t max_send_wqe_inline_cms;
+	uint32_t max_send_wqe_inline_ims;
+	uint32_t max_mw_recursion_depth;
+	uint32_t max_mw_stride_dimenson;
+};
+
+enum ibv_ncm_general_caps {
+	IBV_NCM_SUPPORT_COMPOSITE = 1 << 0,
+	IBV_NCM_SUPPORT_INTERLEAVED = 1 << 1,
+	IBV_NCM_SUPPORT_INTERLEAVED_REPETITION = 1 << 2,
+	IBV_NCM_SUPPORT_INTERLEAVED_NONUNIFORM_REPETITION = 1 << 3,
+	IBV_NCM_SUPPORT_INTERLEAVED_NONUNIFORM_TOTAL_ITEMS = 1 << 4, };
+
 /* RX Hash function flags */
 enum ibv_rx_hash_function_flags {
 	IBV_RX_HASH_FUNC_TOEPLITZ	= 1 << 0,
@@ -256,6 +273,7 @@ struct ibv_device_attr_ex {
 	struct ibv_tso_caps	tso_caps;
 	struct ibv_rss_caps     rss_caps;
 	uint32_t		max_wq_type_rq;
+	struct ibv_ncm_caps     ncm_caps;
 };
 
 enum ibv_mtu {
@@ -472,13 +490,7 @@ enum ibv_access_flags {
 	IBV_ACCESS_MW_BIND		= (1<<4),
 	IBV_ACCESS_ZERO_BASED		= (1<<5),
 	IBV_ACCESS_ON_DEMAND		= (1<<6),
-};
-
-struct ibv_mw_bind_info {
-	struct ibv_mr	*mr;
-	uint64_t	 addr;
-	uint64_t	 length;
-	int		 mw_access_flags; /* use ibv_access_flags */
+	IBV_ACCESS_BIND_MW_NONCONTIG	= (1<<7),
 };
 
 struct ibv_pd {
@@ -533,6 +545,61 @@ struct ibv_mw {
 	enum ibv_mw_type	type;
 };
 
+struct ibv_mw_alloc_attr_ex {
+	unit32_t comp_mask;
+	struct ibv_pd *pd;
+	enum ibv_mw_type type;
+	int max_descriptors;
+};
+
+enum ibv_mw_entry_type {
+	IBV_MW_ENTRY_USE_MR = 0,
+	IBV_MW_ENTRY_USE_MW
+};
+
+struct ibv_mw_bind_layout_entry {
+	uint32_t comp_mask;
+	enum ibv_mw_entry_type mem_obj_type;
+	union mem_obj {
+		struct ibv_mr *mr;
+		struct ibv_mw *mw;
+	};
+	uint64_t addr;
+	uint64_t length;
+	struct {
+		uint64_t repeat_count;
+		uint32_t dimension_count;
+		struct {
+			uint64_t stride;
+			uint64_t count;
+		} *dimension;
+	} interleaved;
+};
+
+enum ibv_mw_bind_layout_type {
+	IBV_MW_BIND_LAYOUT_TYPE_COMPOSITE = 0,
+	IBV_MW_BIND_LAYOUT_TYPE_INTERLEAVED
+};
+
+struct ibv_mw_bind_layout {
+	uint32_t comp_mask;
+	enum ibv_mw_bind_layout_type type;
+	uint32_t entry_count;
+	struct ibv_mw_bind_info_entry *entries; };
+
+struct ibv_mw_bind_info {
+	union {
+		struct {
+			struct ibv_mr   *mr;
+			uint64_t        addr;
+			uint64_t        length;
+		};
+		struct ibv_mw_bind_layout *layout;
+	};
+	int		 mw_access_flags; /* use ibv_access_flags */
+};
+
 struct ibv_global_route {
 	union ibv_gid		dgid;
 	uint32_t		flow_label;
@@ -1411,11 +1478,13 @@ enum verbs_context_mask {
 	VERBS_CONTEXT_QP	= 1 << 2,
 	VERBS_CONTEXT_CREATE_FLOW = 1 << 3,
 	VERBS_CONTEXT_DESTROY_FLOW = 1 << 4,
-	VERBS_CONTEXT_RESERVED	= 1 << 5
+	VERBS_CONTEXT_ALLOC_MW	= 1 << 5,
+	VERBS_CONTEXT_RESERVED	= 1 << 6
 };
 
 struct verbs_context {
 	/*  "grows up" - new fields go here */
+	struct ib_mw * (*alloc_mw_ex)(struct ibv_mw_alloc_attr 
+*mw_alloc_attr);
 	int (*destroy_rwq_ind_table)(struct ibv_rwq_ind_table *rwq_ind_table);
 	struct ibv_rwq_ind_table *(*create_rwq_ind_table)(struct ibv_context *context,
 							  struct ibv_rwq_ind_table_init_attr *init_attr);
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC] Registering non-contiguous memory
       [not found]     ` <DB5PR05MB1270529922F451A2CACF7AE9B95F0-8IvNv+8VlcCeKfjjHlISstqRiQSDpxhJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
@ 2017-11-01 16:56       ` Jason Gunthorpe
       [not found]         ` <20171101165625.GE1030-uk2M96/98Pc@public.gmane.org>
  0 siblings, 1 reply; 12+ messages in thread
From: Jason Gunthorpe @ 2017-11-01 16:56 UTC (permalink / raw)
  To: Alex Margolin
  Cc: 'linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org',
	Leon Romanovsky

On Wed, Nov 01, 2017 at 11:11:42AM +0000, Alex Margolin wrote:

>  struct verbs_context {
>  	/*  "grows up" - new fields go here */
> +	struct ib_mw * (*alloc_mw_ex)(struct ibv_mw_alloc_attr
>  	*mw_alloc_attr);

This patch is full of weird little mistakes like the above, wouldn't
compile and doesn't really seem capture the proposed API.

We are now asking for complete rdma-core patches before talking about
merging new kernel uapi features. Please retry this RFC with the new
requirement.

This means a patch similar to the above, except functional, and all
the man pages and documentation.

The text in the cover letter should go into either into a man page or
a Documentation/ file.

For very complex uapis like this, an simple example usage is also
going to help.

Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC] Registering non-contiguous memory
       [not found]         ` <20171101165625.GE1030-uk2M96/98Pc@public.gmane.org>
@ 2017-11-02  5:09           ` Leon Romanovsky
       [not found]             ` <20171102050942.GU16127-U/DQcQFIOTAAJjI8aNfphQ@public.gmane.org>
  0 siblings, 1 reply; 12+ messages in thread
From: Leon Romanovsky @ 2017-11-02  5:09 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Alex Margolin,
	'linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org'

[-- Attachment #1: Type: text/plain, Size: 1342 bytes --]

On Wed, Nov 01, 2017 at 10:56:25AM -0600, Jason Gunthorpe wrote:
> On Wed, Nov 01, 2017 at 11:11:42AM +0000, Alex Margolin wrote:
>
> >  struct verbs_context {
> >  	/*  "grows up" - new fields go here */
> > +	struct ib_mw * (*alloc_mw_ex)(struct ibv_mw_alloc_attr
> >  	*mw_alloc_attr);
>
> This patch is full of weird little mistakes like the above, wouldn't
> compile and doesn't really seem capture the proposed API.

Those RFCs are intended to present concept and implementation direction.
It is a little bit over-expectation to have working code and clean UAPI
at this stage.

>
> We are now asking for complete rdma-core patches before talking about
> merging new kernel uapi features. Please retry this RFC with the new
> requirement.

There are steps in development process, and first step before rushing
into implementation details is to talk about concept. This is exactly
what Alex did.

>
> This means a patch similar to the above, except functional, and all
> the man pages and documentation.

It already exists in this RFC, just in different format - inlined and
not in patch format.

>
> The text in the cover letter should go into either into a man page or
> a Documentation/ file.

At the implementation phase, yes.

>
> For very complex uapis like this, an simple example usage is also
> going to help.

Agree.

>
> Jason

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC] Registering non-contiguous memory
       [not found]             ` <20171102050942.GU16127-U/DQcQFIOTAAJjI8aNfphQ@public.gmane.org>
@ 2017-11-02 16:12               ` Jason Gunthorpe
       [not found]                 ` <20171102161222.GH18874-uk2M96/98Pc@public.gmane.org>
  0 siblings, 1 reply; 12+ messages in thread
From: Jason Gunthorpe @ 2017-11-02 16:12 UTC (permalink / raw)
  To: Leon Romanovsky
  Cc: Alex Margolin,
	'linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org'

On Thu, Nov 02, 2017 at 07:09:42AM +0200, Leon Romanovsky wrote:
> On Wed, Nov 01, 2017 at 10:56:25AM -0600, Jason Gunthorpe wrote:
> > On Wed, Nov 01, 2017 at 11:11:42AM +0000, Alex Margolin wrote:
> >
> > >  struct verbs_context {
> > >  	/*  "grows up" - new fields go here */
> > > +	struct ib_mw * (*alloc_mw_ex)(struct ibv_mw_alloc_attr
> > >  	*mw_alloc_attr);
> >
> > This patch is full of weird little mistakes like the above, wouldn't
> > compile and doesn't really seem capture the proposed API.
> 
> Those RFCs are intended to present concept and implementation direction.
> It is a little bit over-expectation to have working code and clean UAPI
> at this stage.

Clear communication is important.

If you have to send a code snippit to explain the idea then it had
better 'work'. I'm not asking for an implementation, but certainly
correct changes to verbs.h

> > We are now asking for complete rdma-core patches before talking about
> > merging new kernel uapi features. Please retry this RFC with the new
> > requirement.
> 
> There are steps in development process, and first step before rushing
> into implementation details is to talk about concept. This is exactly
> what Alex did.

Mellanox already did the concept step internally, if you want external
review you need to clearly communicate the idea, and I don't think
these RFCs are detailed or clear enough.

Header file patch, man pages, documentation and an example are the
logical next steps to vet a proposed verbs API in the public forum.

This is analogous to a standards body context, where the next step
would be to draft standards language, eg 'man pages' and API signatures.

Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC] Registering non-contiguous memory
       [not found]                 ` <20171102161222.GH18874-uk2M96/98Pc@public.gmane.org>
@ 2017-11-02 16:31                   ` Leon Romanovsky
       [not found]                     ` <20171102163125.GZ16127-U/DQcQFIOTAAJjI8aNfphQ@public.gmane.org>
  0 siblings, 1 reply; 12+ messages in thread
From: Leon Romanovsky @ 2017-11-02 16:31 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Alex Margolin,
	'linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org'

[-- Attachment #1: Type: text/plain, Size: 2112 bytes --]

On Thu, Nov 02, 2017 at 10:12:22AM -0600, Jason Gunthorpe wrote:
> On Thu, Nov 02, 2017 at 07:09:42AM +0200, Leon Romanovsky wrote:
> > On Wed, Nov 01, 2017 at 10:56:25AM -0600, Jason Gunthorpe wrote:
> > > On Wed, Nov 01, 2017 at 11:11:42AM +0000, Alex Margolin wrote:
> > >
> > > >  struct verbs_context {
> > > >  	/*  "grows up" - new fields go here */
> > > > +	struct ib_mw * (*alloc_mw_ex)(struct ibv_mw_alloc_attr
> > > >  	*mw_alloc_attr);
> > >
> > > This patch is full of weird little mistakes like the above, wouldn't
> > > compile and doesn't really seem capture the proposed API.
> >
> > Those RFCs are intended to present concept and implementation direction.
> > It is a little bit over-expectation to have working code and clean UAPI
> > at this stage.
>
> Clear communication is important.
>
> If you have to send a code snippit to explain the idea then it had
> better 'work'. I'm not asking for an implementation, but certainly
> correct changes to verbs.h
>
> > > We are now asking for complete rdma-core patches before talking about
> > > merging new kernel uapi features. Please retry this RFC with the new
> > > requirement.
> >
> > There are steps in development process, and first step before rushing
> > into implementation details is to talk about concept. This is exactly
> > what Alex did.
>
> Mellanox already did the concept step internally, if you want external
> review you need to clearly communicate the idea, and I don't think
> these RFCs are detailed or clear enough.

Maybe yes and maybe no,
I didn't see anyone in this mailing list who asked more detailed
explanation for Alex's RFC back then. I'm sure that Alex would be
happy to explain it more, if something was unclear.

>
> Header file patch, man pages, documentation and an example are the
> logical next steps to vet a proposed verbs API in the public forum.

And I think that RFC should be much lighter than you wrote. Pseudo API,
motivation and examples.

>
> This is analogous to a standards body context, where the next step
> would be to draft standards language, eg 'man pages' and API signatures.
>
> Jason

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFC] Registering non-contiguous memory
       [not found]                     ` <20171102163125.GZ16127-U/DQcQFIOTAAJjI8aNfphQ@public.gmane.org>
@ 2017-11-02 16:42                       ` Jason Gunthorpe
  0 siblings, 0 replies; 12+ messages in thread
From: Jason Gunthorpe @ 2017-11-02 16:42 UTC (permalink / raw)
  To: Leon Romanovsky
  Cc: Alex Margolin,
	'linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org'

On Thu, Nov 02, 2017 at 06:31:25PM +0200, Leon Romanovsky wrote:
> > Header file patch, man pages, documentation and an example are the
> > logical next steps to vet a proposed verbs API in the public forum.
> 
> And I think that RFC should be much lighter than you wrote. Pseudo API,
> motivation and examples.

The general rule in the kernel community is that things do not get
reviewed without code, and as I said, this specific RFC is confusing,
to say the least.

So if you want some kind of ack that the idea will not be revised when
the code is presented, you need to at least present some code to get it
reviewed.

In this case, man pages and header files would be a reasonable place
to start.

This is particularly true since none of these new RFCs are not backed
by any sort of spec, and the code submission and RFC itself forms the
spec.

Starting by writing the spec is a sane engineering practice.

Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2017-11-02 16:42 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-05 16:46 [RFC] Registering non-contiguous memory Alex Margolin
     [not found] ` <VI1PR05MB127817A311C332553E4391AFB9410-79XLn2atqDMOK6E67s+DINqRiQSDpxhJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2017-02-05 22:44   ` Jason Gunthorpe
     [not found]     ` <20170205224401.GB26474-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2017-03-23 18:21       ` Alex Margolin
     [not found]         ` <DB5PR05MB12702D1DE9A7E7773FF823ACB93F0-8IvNv+8VlcCeKfjjHlISstqRiQSDpxhJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2017-03-23 18:40           ` Jason Gunthorpe
2017-02-28 12:31   ` Tom Talpey
     [not found]     ` <f40f326d-e76b-0471-dc7d-e81b7d07db78-CLs1Zie5N5HQT0dZR+AlfA@public.gmane.org>
2017-03-16 13:32       ` Alex Margolin
2017-11-01 11:11   ` Alex Margolin
     [not found]     ` <DB5PR05MB1270529922F451A2CACF7AE9B95F0-8IvNv+8VlcCeKfjjHlISstqRiQSDpxhJvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>
2017-11-01 16:56       ` Jason Gunthorpe
     [not found]         ` <20171101165625.GE1030-uk2M96/98Pc@public.gmane.org>
2017-11-02  5:09           ` Leon Romanovsky
     [not found]             ` <20171102050942.GU16127-U/DQcQFIOTAAJjI8aNfphQ@public.gmane.org>
2017-11-02 16:12               ` Jason Gunthorpe
     [not found]                 ` <20171102161222.GH18874-uk2M96/98Pc@public.gmane.org>
2017-11-02 16:31                   ` Leon Romanovsky
     [not found]                     ` <20171102163125.GZ16127-U/DQcQFIOTAAJjI8aNfphQ@public.gmane.org>
2017-11-02 16:42                       ` Jason Gunthorpe

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.