Skip to content

Commit c8da19b

Browse files
Trond MyklebustTrond Myklebust
authored andcommitted
NFSv4.1: Fix an ABBA locking issue with session and state serialisation
Ensure that if nfs_wait_on_sequence() causes our rpc task to wait for an NFSv4 state serialisation lock, then we also drop the session slot. Signed-off-by: Trond Myklebust <[email protected]> Cc: [email protected]
1 parent c21443c commit c8da19b

File tree

1 file changed

+20
-12
lines changed

1 file changed

+20
-12
lines changed

fs/nfs/nfs4proc.c

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,7 +1466,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
14661466
struct nfs4_state_owner *sp = data->owner;
14671467

14681468
if (nfs_wait_on_sequence(data->o_arg.seqid, task) != 0)
1469-
return;
1469+
goto out_wait;
14701470
/*
14711471
* Check if we still need to send an OPEN call, or if we can use
14721472
* a delegation instead.
@@ -1501,6 +1501,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
15011501
rcu_read_unlock();
15021502
out_no_action:
15031503
task->tk_action = NULL;
1504+
out_wait:
15041505
nfs4_sequence_done(task, &data->o_res.seq_res);
15051506
}
15061507

@@ -2179,7 +2180,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
21792180

21802181
dprintk("%s: begin!\n", __func__);
21812182
if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
2182-
return;
2183+
goto out_wait;
21832184

21842185
task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
21852186
calldata->arg.fmode = FMODE_READ|FMODE_WRITE;
@@ -2201,16 +2202,14 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
22012202

22022203
if (!call_close) {
22032204
/* Note: exit _without_ calling nfs4_close_done */
2204-
task->tk_action = NULL;
2205-
nfs4_sequence_done(task, &calldata->res.seq_res);
2206-
goto out;
2205+
goto out_no_action;
22072206
}
22082207

22092208
if (calldata->arg.fmode == 0) {
22102209
task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE];
22112210
if (calldata->roc &&
22122211
pnfs_roc_drain(inode, &calldata->roc_barrier, task))
2213-
goto out;
2212+
goto out_wait;
22142213
}
22152214

22162215
nfs_fattr_init(calldata->res.fattr);
@@ -2220,8 +2219,12 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
22202219
&calldata->res.seq_res,
22212220
task) != 0)
22222221
nfs_release_seqid(calldata->arg.seqid);
2223-
out:
22242222
dprintk("%s: done!\n", __func__);
2223+
return;
2224+
out_no_action:
2225+
task->tk_action = NULL;
2226+
out_wait:
2227+
nfs4_sequence_done(task, &calldata->res.seq_res);
22252228
}
22262229

22272230
static const struct rpc_call_ops nfs4_close_ops = {
@@ -4452,19 +4455,22 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
44524455
struct nfs4_unlockdata *calldata = data;
44534456

44544457
if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
4455-
return;
4458+
goto out_wait;
44564459
if (test_bit(NFS_LOCK_INITIALIZED, &calldata->lsp->ls_flags) == 0) {
44574460
/* Note: exit _without_ running nfs4_locku_done */
4458-
task->tk_action = NULL;
4459-
nfs4_sequence_done(task, &calldata->res.seq_res);
4460-
return;
4461+
goto out_no_action;
44614462
}
44624463
calldata->timestamp = jiffies;
44634464
if (nfs4_setup_sequence(calldata->server,
44644465
&calldata->arg.seq_args,
44654466
&calldata->res.seq_res,
44664467
task) != 0)
44674468
nfs_release_seqid(calldata->arg.seqid);
4469+
return;
4470+
out_no_action:
4471+
task->tk_action = NULL;
4472+
out_wait:
4473+
nfs4_sequence_done(task, &calldata->res.seq_res);
44684474
}
44694475

44704476
static const struct rpc_call_ops nfs4_locku_ops = {
@@ -4612,7 +4618,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
46124618

46134619
dprintk("%s: begin!\n", __func__);
46144620
if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0)
4615-
return;
4621+
goto out_wait;
46164622
/* Do we need to do an open_to_lock_owner? */
46174623
if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {
46184624
if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) {
@@ -4632,6 +4638,8 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
46324638
nfs_release_seqid(data->arg.open_seqid);
46334639
out_release_lock_seqid:
46344640
nfs_release_seqid(data->arg.lock_seqid);
4641+
out_wait:
4642+
nfs4_sequence_done(task, &data->res.seq_res);
46354643
dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
46364644
}
46374645

0 commit comments

Comments
 (0)