diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-03-01 17:00:56 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-03-02 15:36:38 -0500 |
commit | 2446ab6070861aba2dd9229463ffbc40016a9f33 (patch) | |
tree | 2e366c3236788936b9f4f58c0787ae01c265f4a4 /net/sunrpc/rpcb_clnt.c | |
parent | a3ca5651cb5eebe2e56e510bbf5cd60abc301c9f (diff) |
SUNRPC: Use RCU to dereference the rpc_clnt.cl_xprt field
A migration event will replace the rpc_xprt used by an rpc_clnt. To
ensure this can be done safely, all references to cl_xprt must now use
a form of rcu_dereference().
Special care is taken with rpc_peeraddr2str(), which returns a pointer
to memory whose lifetime is the same as the rpc_xprt.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
[ cel: fix lockdep splats and layering violations ]
[ cel: forward ported to 3.4 ]
[ cel: remove rpc_max_reqs(), add rpc_net_ns() ]
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/rpcb_clnt.c')
-rw-r--r-- | net/sunrpc/rpcb_clnt.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index b1f08bd67883..4f8af63798a2 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
@@ -620,9 +620,10 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi | |||
620 | static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt) | 620 | static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt) |
621 | { | 621 | { |
622 | struct rpc_clnt *parent = clnt->cl_parent; | 622 | struct rpc_clnt *parent = clnt->cl_parent; |
623 | struct rpc_xprt *xprt = rcu_dereference(clnt->cl_xprt); | ||
623 | 624 | ||
624 | while (parent != clnt) { | 625 | while (parent != clnt) { |
625 | if (parent->cl_xprt != clnt->cl_xprt) | 626 | if (rcu_dereference(parent->cl_xprt) != xprt) |
626 | break; | 627 | break; |
627 | if (clnt->cl_autobind) | 628 | if (clnt->cl_autobind) |
628 | break; | 629 | break; |
@@ -653,8 +654,12 @@ void rpcb_getport_async(struct rpc_task *task) | |||
653 | size_t salen; | 654 | size_t salen; |
654 | int status; | 655 | int status; |
655 | 656 | ||
656 | clnt = rpcb_find_transport_owner(task->tk_client); | 657 | rcu_read_lock(); |
657 | xprt = clnt->cl_xprt; | 658 | do { |
659 | clnt = rpcb_find_transport_owner(task->tk_client); | ||
660 | xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); | ||
661 | } while (xprt == NULL); | ||
662 | rcu_read_unlock(); | ||
658 | 663 | ||
659 | dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", | 664 | dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", |
660 | task->tk_pid, __func__, | 665 | task->tk_pid, __func__, |
@@ -667,6 +672,7 @@ void rpcb_getport_async(struct rpc_task *task) | |||
667 | if (xprt_test_and_set_binding(xprt)) { | 672 | if (xprt_test_and_set_binding(xprt)) { |
668 | dprintk("RPC: %5u %s: waiting for another binder\n", | 673 | dprintk("RPC: %5u %s: waiting for another binder\n", |
669 | task->tk_pid, __func__); | 674 | task->tk_pid, __func__); |
675 | xprt_put(xprt); | ||
670 | return; | 676 | return; |
671 | } | 677 | } |
672 | 678 | ||
@@ -734,7 +740,7 @@ void rpcb_getport_async(struct rpc_task *task) | |||
734 | switch (bind_version) { | 740 | switch (bind_version) { |
735 | case RPCBVERS_4: | 741 | case RPCBVERS_4: |
736 | case RPCBVERS_3: | 742 | case RPCBVERS_3: |
737 | map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); | 743 | map->r_netid = xprt->address_strings[RPC_DISPLAY_NETID]; |
738 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_ATOMIC); | 744 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_ATOMIC); |
739 | map->r_owner = ""; | 745 | map->r_owner = ""; |
740 | break; | 746 | break; |
@@ -763,6 +769,7 @@ bailout_release_client: | |||
763 | bailout_nofree: | 769 | bailout_nofree: |
764 | rpcb_wake_rpcbind_waiters(xprt, status); | 770 | rpcb_wake_rpcbind_waiters(xprt, status); |
765 | task->tk_status = status; | 771 | task->tk_status = status; |
772 | xprt_put(xprt); | ||
766 | } | 773 | } |
767 | EXPORT_SYMBOL_GPL(rpcb_getport_async); | 774 | EXPORT_SYMBOL_GPL(rpcb_getport_async); |
768 | 775 | ||