Skip to content

Commit fce5c83

Browse files
labiagaTrond Myklebust
authored andcommitted
nfs41: RECLAIM_COMPLETE functionality
Implements RECLAIM_COMPLETE as an asynchronous RPC. NFS4ERR_DELAY is retried, NFS4ERR_DEADSESSION invokes the error handling but does not result in a retry, since we don't want to have a lingering RECLAIM_COMPLETE call sent in the middle of a possible new state recovery cycle. If a session reset occurs, a new wave of reclaim operations will follow, containing their own RECLAIM_COMPLETE call. We don't want a retry to get on the way of recovery by incorrectly indicating to the server that we're done reclaiming state. A subsequent patch invokes the functionality. Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
1 parent 1801975 commit fce5c83

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed

fs/nfs/nfs4_fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ struct nfs4_state_recovery_ops {
181181
int (*recover_lock)(struct nfs4_state *, struct file_lock *);
182182
int (*establish_clid)(struct nfs_client *, struct rpc_cred *);
183183
struct rpc_cred * (*get_clid_cred)(struct nfs_client *);
184+
int (*reclaim_complete)(struct nfs_client *);
184185
};
185186

186187
struct nfs4_state_maintenance_ops {

fs/nfs/nfs4proc.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4971,6 +4971,110 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp,
49714971
&nfs41_sequence_ops, (void *)clp);
49724972
}
49734973

4974+
struct nfs4_reclaim_complete_data {
4975+
struct nfs_client *clp;
4976+
struct nfs41_reclaim_complete_args arg;
4977+
struct nfs41_reclaim_complete_res res;
4978+
};
4979+
4980+
static void nfs4_reclaim_complete_prepare(struct rpc_task *task, void *data)
4981+
{
4982+
struct nfs4_reclaim_complete_data *calldata = data;
4983+
4984+
if (nfs4_setup_sequence(calldata->clp, &calldata->arg.seq_args,
4985+
&calldata->res.seq_res, 0, task))
4986+
return;
4987+
4988+
rpc_call_start(task);
4989+
}
4990+
4991+
static void nfs4_reclaim_complete_done(struct rpc_task *task, void *data)
4992+
{
4993+
struct nfs4_reclaim_complete_data *calldata = data;
4994+
struct nfs_client *clp = calldata->clp;
4995+
struct nfs4_sequence_res *res = &calldata->res.seq_res;
4996+
4997+
dprintk("--> %s\n", __func__);
4998+
nfs41_sequence_done(clp, res, task->tk_status);
4999+
switch (task->tk_status) {
5000+
case 0:
5001+
case -NFS4ERR_COMPLETE_ALREADY:
5002+
break;
5003+
case -NFS4ERR_BADSESSION:
5004+
case -NFS4ERR_DEADSESSION:
5005+
/*
5006+
* Handle the session error, but do not retry the operation, as
5007+
* we have no way of telling whether the clientid had to be
5008+
* reset before we got our reply. If reset, a new wave of
5009+
* reclaim operations will follow, containing their own reclaim
5010+
* complete. We don't want our retry to get on the way of
5011+
* recovery by incorrectly indicating to the server that we're
5012+
* done reclaiming state since the process had to be restarted.
5013+
*/
5014+
_nfs4_async_handle_error(task, NULL, clp, NULL);
5015+
break;
5016+
default:
5017+
if (_nfs4_async_handle_error(
5018+
task, NULL, clp, NULL) == -EAGAIN) {
5019+
rpc_restart_call_prepare(task);
5020+
return;
5021+
}
5022+
}
5023+
nfs41_sequence_free_slot(clp, res);
5024+
5025+
dprintk("<-- %s\n", __func__);
5026+
}
5027+
5028+
static void nfs4_free_reclaim_complete_data(void *data)
5029+
{
5030+
struct nfs4_reclaim_complete_data *calldata = data;
5031+
5032+
kfree(calldata);
5033+
}
5034+
5035+
static const struct rpc_call_ops nfs4_reclaim_complete_call_ops = {
5036+
.rpc_call_prepare = nfs4_reclaim_complete_prepare,
5037+
.rpc_call_done = nfs4_reclaim_complete_done,
5038+
.rpc_release = nfs4_free_reclaim_complete_data,
5039+
};
5040+
5041+
/*
5042+
* Issue a global reclaim complete.
5043+
*/
5044+
static int nfs41_proc_reclaim_complete(struct nfs_client *clp)
5045+
{
5046+
struct nfs4_reclaim_complete_data *calldata;
5047+
struct rpc_task *task;
5048+
struct rpc_message msg = {
5049+
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RECLAIM_COMPLETE],
5050+
};
5051+
struct rpc_task_setup task_setup_data = {
5052+
.rpc_client = clp->cl_rpcclient,
5053+
.rpc_message = &msg,
5054+
.callback_ops = &nfs4_reclaim_complete_call_ops,
5055+
.flags = RPC_TASK_ASYNC,
5056+
};
5057+
int status = -ENOMEM;
5058+
5059+
dprintk("--> %s\n", __func__);
5060+
calldata = kzalloc(sizeof(*calldata), GFP_KERNEL);
5061+
if (calldata == NULL)
5062+
goto out;
5063+
calldata->clp = clp;
5064+
calldata->arg.one_fs = 0;
5065+
calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
5066+
5067+
msg.rpc_argp = &calldata->arg;
5068+
msg.rpc_resp = &calldata->res;
5069+
task_setup_data.callback_data = calldata;
5070+
task = rpc_run_task(&task_setup_data);
5071+
if (IS_ERR(task))
5072+
status = PTR_ERR(task);
5073+
rpc_put_task(task);
5074+
out:
5075+
dprintk("<-- %s status=%d\n", __func__, status);
5076+
return status;
5077+
}
49745078
#endif /* CONFIG_NFS_V4_1 */
49755079

49765080
struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
@@ -4990,6 +5094,7 @@ struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = {
49905094
.recover_lock = nfs4_lock_reclaim,
49915095
.establish_clid = nfs41_init_clientid,
49925096
.get_clid_cred = nfs4_get_exchange_id_cred,
5097+
.reclaim_complete = nfs41_proc_reclaim_complete,
49935098
};
49945099
#endif /* CONFIG_NFS_V4_1 */
49955100

fs/nfs/nfs4state.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,14 @@ static void nfs4_state_start_reclaim_reboot(struct nfs_client *clp)
10321032
nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_reboot);
10331033
}
10341034

1035+
static void nfs4_reclaim_complete(struct nfs_client *clp,
1036+
const struct nfs4_state_recovery_ops *ops)
1037+
{
1038+
/* Notify the server we're done reclaiming our state */
1039+
if (ops->reclaim_complete)
1040+
(void)ops->reclaim_complete(clp);
1041+
}
1042+
10351043
static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
10361044
{
10371045
struct nfs4_state_owner *sp;

0 commit comments

Comments
 (0)