aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorBryan Schumaker <bjschuma@netapp.com>2012-11-12 16:55:38 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-11-20 23:34:54 -0500
commit6bdb5f213c4344324f600dde885f25768fbd14db (patch)
tree6823ca803d7b6b26c81118eb91b0e4e825c9a78f /fs/nfs
parentf994c43d19a9116727d4c228d3f13db595bff562 (diff)
NFS: Add sequence_priviliged_ops for nfs4_proc_sequence()
If I mount an NFS v4.1 server to a single client multiple times and then run xfstests over each mountpoint I usually get the client into a state where recovery deadlocks. The server informs the client of a cb_path_down sequence error, the client then does a bind_connection_to_session and checks the status of the lease. I found that bind_connection_to_session sets the NFS4_SESSION_DRAINING flag on the client, but this flag is never unset before nfs4_check_lease() reaches nfs4_proc_sequence(). This causes the client to deadlock, halting all NFS activity to the server. nfs4_proc_sequence() is only called by the state manager, so I can change it to run in privileged mode to bypass the NFS4_SESSION_DRAINING check and avoid the deadlock. Signed-off-by: Bryan Schumaker <bjschuma@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Cc: stable@vger.kernel.org
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4proc.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 6300cdd81101..a32d953b08de 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6136,13 +6136,26 @@ static void nfs41_sequence_prepare(struct rpc_task *task, void *data)
6136 rpc_call_start(task); 6136 rpc_call_start(task);
6137} 6137}
6138 6138
6139static void nfs41_sequence_prepare_privileged(struct rpc_task *task, void *data)
6140{
6141 rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
6142 nfs41_sequence_prepare(task, data);
6143}
6144
6139static const struct rpc_call_ops nfs41_sequence_ops = { 6145static const struct rpc_call_ops nfs41_sequence_ops = {
6140 .rpc_call_done = nfs41_sequence_call_done, 6146 .rpc_call_done = nfs41_sequence_call_done,
6141 .rpc_call_prepare = nfs41_sequence_prepare, 6147 .rpc_call_prepare = nfs41_sequence_prepare,
6142 .rpc_release = nfs41_sequence_release, 6148 .rpc_release = nfs41_sequence_release,
6143}; 6149};
6144 6150
6145static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) 6151static const struct rpc_call_ops nfs41_sequence_privileged_ops = {
6152 .rpc_call_done = nfs41_sequence_call_done,
6153 .rpc_call_prepare = nfs41_sequence_prepare_privileged,
6154 .rpc_release = nfs41_sequence_release,
6155};
6156
6157static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred,
6158 const struct rpc_call_ops *seq_ops)
6146{ 6159{
6147 struct nfs4_sequence_data *calldata; 6160 struct nfs4_sequence_data *calldata;
6148 struct rpc_message msg = { 6161 struct rpc_message msg = {
@@ -6152,7 +6165,7 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_
6152 struct rpc_task_setup task_setup_data = { 6165 struct rpc_task_setup task_setup_data = {
6153 .rpc_client = clp->cl_rpcclient, 6166 .rpc_client = clp->cl_rpcclient,
6154 .rpc_message = &msg, 6167 .rpc_message = &msg,
6155 .callback_ops = &nfs41_sequence_ops, 6168 .callback_ops = seq_ops,
6156 .flags = RPC_TASK_ASYNC | RPC_TASK_SOFT, 6169 .flags = RPC_TASK_ASYNC | RPC_TASK_SOFT,
6157 }; 6170 };
6158 6171
@@ -6179,7 +6192,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cr
6179 6192
6180 if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0) 6193 if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0)
6181 return 0; 6194 return 0;
6182 task = _nfs41_proc_sequence(clp, cred); 6195 task = _nfs41_proc_sequence(clp, cred, &nfs41_sequence_ops);
6183 if (IS_ERR(task)) 6196 if (IS_ERR(task))
6184 ret = PTR_ERR(task); 6197 ret = PTR_ERR(task);
6185 else 6198 else
@@ -6193,7 +6206,7 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
6193 struct rpc_task *task; 6206 struct rpc_task *task;
6194 int ret; 6207 int ret;
6195 6208
6196 task = _nfs41_proc_sequence(clp, cred); 6209 task = _nfs41_proc_sequence(clp, cred, &nfs41_sequence_privileged_ops);
6197 if (IS_ERR(task)) { 6210 if (IS_ERR(task)) {
6198 ret = PTR_ERR(task); 6211 ret = PTR_ERR(task);
6199 goto out; 6212 goto out;