diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-10-29 18:37:40 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-10-31 15:08:18 -0400 |
commit | 2240a9e2d013d8269ea425b73e1d7a54c7bc141f (patch) | |
tree | e213bd7362b0cb816c3ed0e530bb2390012bcc6c /fs | |
parent | 399f11c3d872bd748e1575574de265a6304c7c43 (diff) |
NFSv4.1: We must release the sequence id when we fail to get a session slot
If we do not release the sequence id in cases where we fail to get a
session slot, then we can deadlock if we hit a recovery scenario.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Cc: stable@vger.kernel.org
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/nfs4proc.c | 36 |
1 files changed, 23 insertions, 13 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index d5fbf1f49d5f..e0423bb5a880 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1571,9 +1571,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) | |||
1571 | data->timestamp = jiffies; | 1571 | data->timestamp = jiffies; |
1572 | if (nfs4_setup_sequence(data->o_arg.server, | 1572 | if (nfs4_setup_sequence(data->o_arg.server, |
1573 | &data->o_arg.seq_args, | 1573 | &data->o_arg.seq_args, |
1574 | &data->o_res.seq_res, task)) | 1574 | &data->o_res.seq_res, |
1575 | return; | 1575 | task) != 0) |
1576 | rpc_call_start(task); | 1576 | nfs_release_seqid(data->o_arg.seqid); |
1577 | else | ||
1578 | rpc_call_start(task); | ||
1577 | return; | 1579 | return; |
1578 | unlock_no_action: | 1580 | unlock_no_action: |
1579 | rcu_read_unlock(); | 1581 | rcu_read_unlock(); |
@@ -2295,9 +2297,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
2295 | if (nfs4_setup_sequence(NFS_SERVER(inode), | 2297 | if (nfs4_setup_sequence(NFS_SERVER(inode), |
2296 | &calldata->arg.seq_args, | 2298 | &calldata->arg.seq_args, |
2297 | &calldata->res.seq_res, | 2299 | &calldata->res.seq_res, |
2298 | task)) | 2300 | task) != 0) |
2299 | goto out; | 2301 | nfs_release_seqid(calldata->arg.seqid); |
2300 | rpc_call_start(task); | 2302 | else |
2303 | rpc_call_start(task); | ||
2301 | out: | 2304 | out: |
2302 | dprintk("%s: done!\n", __func__); | 2305 | dprintk("%s: done!\n", __func__); |
2303 | } | 2306 | } |
@@ -4544,9 +4547,11 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) | |||
4544 | calldata->timestamp = jiffies; | 4547 | calldata->timestamp = jiffies; |
4545 | if (nfs4_setup_sequence(calldata->server, | 4548 | if (nfs4_setup_sequence(calldata->server, |
4546 | &calldata->arg.seq_args, | 4549 | &calldata->arg.seq_args, |
4547 | &calldata->res.seq_res, task)) | 4550 | &calldata->res.seq_res, |
4548 | return; | 4551 | task) != 0) |
4549 | rpc_call_start(task); | 4552 | nfs_release_seqid(calldata->arg.seqid); |
4553 | else | ||
4554 | rpc_call_start(task); | ||
4550 | } | 4555 | } |
4551 | 4556 | ||
4552 | static const struct rpc_call_ops nfs4_locku_ops = { | 4557 | static const struct rpc_call_ops nfs4_locku_ops = { |
@@ -4691,7 +4696,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) | |||
4691 | /* Do we need to do an open_to_lock_owner? */ | 4696 | /* Do we need to do an open_to_lock_owner? */ |
4692 | if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { | 4697 | if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { |
4693 | if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) | 4698 | if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) |
4694 | return; | 4699 | goto out_release_lock_seqid; |
4695 | data->arg.open_stateid = &state->stateid; | 4700 | data->arg.open_stateid = &state->stateid; |
4696 | data->arg.new_lock_owner = 1; | 4701 | data->arg.new_lock_owner = 1; |
4697 | data->res.open_seqid = data->arg.open_seqid; | 4702 | data->res.open_seqid = data->arg.open_seqid; |
@@ -4700,10 +4705,15 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) | |||
4700 | data->timestamp = jiffies; | 4705 | data->timestamp = jiffies; |
4701 | if (nfs4_setup_sequence(data->server, | 4706 | if (nfs4_setup_sequence(data->server, |
4702 | &data->arg.seq_args, | 4707 | &data->arg.seq_args, |
4703 | &data->res.seq_res, task)) | 4708 | &data->res.seq_res, |
4709 | task) == 0) { | ||
4710 | rpc_call_start(task); | ||
4704 | return; | 4711 | return; |
4705 | rpc_call_start(task); | 4712 | } |
4706 | dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); | 4713 | nfs_release_seqid(data->arg.open_seqid); |
4714 | out_release_lock_seqid: | ||
4715 | nfs_release_seqid(data->arg.lock_seqid); | ||
4716 | dprintk("%s: done!, ret = %d\n", __func__, task->tk_status); | ||
4707 | } | 4717 | } |
4708 | 4718 | ||
4709 | static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata) | 4719 | static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata) |