xprtrdma: Use an llist to manage free rpcrdma_reps
rpcrdma_rep objects are removed from their free list by only a single thread: the Receive completion handler. Thus that free list can be converted to an llist, where a single-threaded consumer and a multi-threaded producer (rpcrdma_buffer_put) can both access the llist without the need for any serialization. This eliminates spin lock contention between the Receive completion handler and rpcrdma_buffer_get, and makes the rep consumer wait- free. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:

committed by
Anna Schumaker

parent
4d6b8890dd
commit
b0b227f071
@@ -47,6 +47,7 @@
|
||||
#include <linux/atomic.h> /* atomic_t, etc */
|
||||
#include <linux/kref.h> /* struct kref */
|
||||
#include <linux/workqueue.h> /* struct work_struct */
|
||||
#include <linux/llist.h>
|
||||
|
||||
#include <rdma/rdma_cm.h> /* RDMA connection api */
|
||||
#include <rdma/ib_verbs.h> /* RDMA verbs api */
|
||||
@@ -200,7 +201,7 @@ struct rpcrdma_rep {
|
||||
struct rpc_rqst *rr_rqst;
|
||||
struct xdr_buf rr_hdrbuf;
|
||||
struct xdr_stream rr_stream;
|
||||
struct list_head rr_list;
|
||||
struct llist_node rr_node;
|
||||
struct ib_recv_wr rr_recv_wr;
|
||||
};
|
||||
|
||||
@@ -362,7 +363,6 @@ rpcrdma_mr_pop(struct list_head *list)
|
||||
struct rpcrdma_buffer {
|
||||
spinlock_t rb_lock;
|
||||
struct list_head rb_send_bufs;
|
||||
struct list_head rb_recv_bufs;
|
||||
struct list_head rb_mrs;
|
||||
|
||||
unsigned long rb_sc_head;
|
||||
@@ -373,6 +373,8 @@ struct rpcrdma_buffer {
|
||||
struct list_head rb_allreqs;
|
||||
struct list_head rb_all_mrs;
|
||||
|
||||
struct llist_head rb_free_reps;
|
||||
|
||||
u32 rb_max_requests;
|
||||
u32 rb_credits; /* most recent credit grant */
|
||||
|
||||
|
Reference in New Issue
Block a user