diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2014-05-28 10:32:17 -0400 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2014-06-04 08:56:36 -0400 |
commit | 254f91e2fa1f4cc18fd2eb9d5481888ffe126d5b (patch) | |
tree | 59ee9a80d0ab6a7875cf9b9e47337b36e2744d92 /net/sunrpc | |
parent | 4034ba04231f554abb97ad8900a4c1af03f8e21d (diff) |
xprtrdma: RPC/RDMA must invoke xprt_wake_pending_tasks() in process context
An IB provider can invoke rpcrdma_conn_func() in an IRQ context,
thus rpcrdma_conn_func() cannot be allowed to directly invoke
generic RPC functions like xprt_wake_pending_tasks().
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Tested-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/xprtrdma/rpc_rdma.c | 22 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/verbs.c | 3 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/xprt_rdma.h | 3 |
3 files changed, 21 insertions, 7 deletions
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 400aa1b77d72..c296468a6f96 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c | |||
@@ -676,15 +676,11 @@ rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len, int pad) | |||
676 | rqst->rq_private_buf = rqst->rq_rcv_buf; | 676 | rqst->rq_private_buf = rqst->rq_rcv_buf; |
677 | } | 677 | } |
678 | 678 | ||
679 | /* | ||
680 | * This function is called when an async event is posted to | ||
681 | * the connection which changes the connection state. All it | ||
682 | * does at this point is mark the connection up/down, the rpc | ||
683 | * timers do the rest. | ||
684 | */ | ||
685 | void | 679 | void |
686 | rpcrdma_conn_func(struct rpcrdma_ep *ep) | 680 | rpcrdma_connect_worker(struct work_struct *work) |
687 | { | 681 | { |
682 | struct rpcrdma_ep *ep = | ||
683 | container_of(work, struct rpcrdma_ep, rep_connect_worker.work); | ||
688 | struct rpc_xprt *xprt = ep->rep_xprt; | 684 | struct rpc_xprt *xprt = ep->rep_xprt; |
689 | 685 | ||
690 | spin_lock_bh(&xprt->transport_lock); | 686 | spin_lock_bh(&xprt->transport_lock); |
@@ -701,6 +697,18 @@ rpcrdma_conn_func(struct rpcrdma_ep *ep) | |||
701 | } | 697 | } |
702 | 698 | ||
703 | /* | 699 | /* |
700 | * This function is called when an async event is posted to | ||
701 | * the connection which changes the connection state. All it | ||
702 | * does at this point is mark the connection up/down, the rpc | ||
703 | * timers do the rest. | ||
704 | */ | ||
705 | void | ||
706 | rpcrdma_conn_func(struct rpcrdma_ep *ep) | ||
707 | { | ||
708 | schedule_delayed_work(&ep->rep_connect_worker, 0); | ||
709 | } | ||
710 | |||
711 | /* | ||
704 | * This function is called when memory window unbind which we are waiting | 712 | * This function is called when memory window unbind which we are waiting |
705 | * for completes. Just use rr_func (zeroed by upcall) to signal completion. | 713 | * for completes. Just use rr_func (zeroed by upcall) to signal completion. |
706 | */ | 714 | */ |
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 8f9704e0f03d..9cb88f373c7a 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c | |||
@@ -742,6 +742,7 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia, | |||
742 | INIT_CQCOUNT(ep); | 742 | INIT_CQCOUNT(ep); |
743 | ep->rep_ia = ia; | 743 | ep->rep_ia = ia; |
744 | init_waitqueue_head(&ep->rep_connect_wait); | 744 | init_waitqueue_head(&ep->rep_connect_wait); |
745 | INIT_DELAYED_WORK(&ep->rep_connect_worker, rpcrdma_connect_worker); | ||
745 | 746 | ||
746 | /* | 747 | /* |
747 | * Create a single cq for receive dto and mw_bind (only ever | 748 | * Create a single cq for receive dto and mw_bind (only ever |
@@ -817,6 +818,8 @@ rpcrdma_ep_destroy(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) | |||
817 | dprintk("RPC: %s: entering, connected is %d\n", | 818 | dprintk("RPC: %s: entering, connected is %d\n", |
818 | __func__, ep->rep_connected); | 819 | __func__, ep->rep_connected); |
819 | 820 | ||
821 | cancel_delayed_work_sync(&ep->rep_connect_worker); | ||
822 | |||
820 | if (ia->ri_id->qp) { | 823 | if (ia->ri_id->qp) { |
821 | rc = rpcrdma_ep_disconnect(ep, ia); | 824 | rc = rpcrdma_ep_disconnect(ep, ia); |
822 | if (rc) | 825 | if (rc) |
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index 98340a31f2bc..c620d1332933 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/wait.h> /* wait_queue_head_t, etc */ | 43 | #include <linux/wait.h> /* wait_queue_head_t, etc */ |
44 | #include <linux/spinlock.h> /* spinlock_t, etc */ | 44 | #include <linux/spinlock.h> /* spinlock_t, etc */ |
45 | #include <linux/atomic.h> /* atomic_t, etc */ | 45 | #include <linux/atomic.h> /* atomic_t, etc */ |
46 | #include <linux/workqueue.h> /* struct work_struct */ | ||
46 | 47 | ||
47 | #include <rdma/rdma_cm.h> /* RDMA connection api */ | 48 | #include <rdma/rdma_cm.h> /* RDMA connection api */ |
48 | #include <rdma/ib_verbs.h> /* RDMA verbs api */ | 49 | #include <rdma/ib_verbs.h> /* RDMA verbs api */ |
@@ -87,6 +88,7 @@ struct rpcrdma_ep { | |||
87 | struct rpc_xprt *rep_xprt; /* for rep_func */ | 88 | struct rpc_xprt *rep_xprt; /* for rep_func */ |
88 | struct rdma_conn_param rep_remote_cma; | 89 | struct rdma_conn_param rep_remote_cma; |
89 | struct sockaddr_storage rep_remote_addr; | 90 | struct sockaddr_storage rep_remote_addr; |
91 | struct delayed_work rep_connect_worker; | ||
90 | }; | 92 | }; |
91 | 93 | ||
92 | #define INIT_CQCOUNT(ep) atomic_set(&(ep)->rep_cqcount, (ep)->rep_cqinit) | 94 | #define INIT_CQCOUNT(ep) atomic_set(&(ep)->rep_cqcount, (ep)->rep_cqinit) |
@@ -336,6 +338,7 @@ int rpcrdma_deregister_external(struct rpcrdma_mr_seg *, | |||
336 | /* | 338 | /* |
337 | * RPC/RDMA connection management calls - xprtrdma/rpc_rdma.c | 339 | * RPC/RDMA connection management calls - xprtrdma/rpc_rdma.c |
338 | */ | 340 | */ |
341 | void rpcrdma_connect_worker(struct work_struct *); | ||
339 | void rpcrdma_conn_func(struct rpcrdma_ep *); | 342 | void rpcrdma_conn_func(struct rpcrdma_ep *); |
340 | void rpcrdma_reply_handler(struct rpcrdma_rep *); | 343 | void rpcrdma_reply_handler(struct rpcrdma_rep *); |
341 | 344 | ||