aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4state.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-03-01 17:00:56 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-03-02 15:36:38 -0500
commit2446ab6070861aba2dd9229463ffbc40016a9f33 (patch)
tree2e366c3236788936b9f4f58c0787ae01c265f4a4 /fs/nfs/nfs4state.c
parenta3ca5651cb5eebe2e56e510bbf5cd60abc301c9f (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 'fs/nfs/nfs4state.c')
-rw-r--r--fs/nfs/nfs4state.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index c1111a37dc14..bae959e294cd 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1037,19 +1037,28 @@ static void nfs4_clear_state_manager_bit(struct nfs_client *clp)
1037void nfs4_schedule_state_manager(struct nfs_client *clp) 1037void nfs4_schedule_state_manager(struct nfs_client *clp)
1038{ 1038{
1039 struct task_struct *task; 1039 struct task_struct *task;
1040 char buf[INET6_ADDRSTRLEN + sizeof("-manager") + 1];
1040 1041
1041 if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) 1042 if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
1042 return; 1043 return;
1043 __module_get(THIS_MODULE); 1044 __module_get(THIS_MODULE);
1044 atomic_inc(&clp->cl_count); 1045 atomic_inc(&clp->cl_count);
1045 task = kthread_run(nfs4_run_state_manager, clp, "%s-manager", 1046
1046 rpc_peeraddr2str(clp->cl_rpcclient, 1047 /* The rcu_read_lock() is not strictly necessary, as the state
1047 RPC_DISPLAY_ADDR)); 1048 * manager is the only thread that ever changes the rpc_xprt
1048 if (!IS_ERR(task)) 1049 * after it's initialized. At this point, we're single threaded. */
1049 return; 1050 rcu_read_lock();
1050 nfs4_clear_state_manager_bit(clp); 1051 snprintf(buf, sizeof(buf), "%s-manager",
1051 nfs_put_client(clp); 1052 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR));
1052 module_put(THIS_MODULE); 1053 rcu_read_unlock();
1054 task = kthread_run(nfs4_run_state_manager, clp, buf);
1055 if (IS_ERR(task)) {
1056 printk(KERN_ERR "%s: kthread_run: %ld\n",
1057 __func__, PTR_ERR(task));
1058 nfs4_clear_state_manager_bit(clp);
1059 nfs_put_client(clp);
1060 module_put(THIS_MODULE);
1061 }
1053} 1062}
1054 1063
1055/* 1064/*