|
@@ -623,24 +623,39 @@ nfsd4_cb_layout_done(struct nfsd4_callback *cb, struct rpc_task *task)
|
|
|
{
|
|
|
struct nfs4_layout_stateid *ls =
|
|
|
container_of(cb, struct nfs4_layout_stateid, ls_recall);
|
|
|
+ struct nfsd_net *nn;
|
|
|
+ ktime_t now, cutoff;
|
|
|
LIST_HEAD(reaplist);
|
|
|
|
|
|
+
|
|
|
switch (task->tk_status) {
|
|
|
case 0:
|
|
|
- return 1;
|
|
|
+ case -NFS4ERR_DELAY:
|
|
|
+ /*
|
|
|
+ * Anything left? If not, then call it done. Note that we don't
|
|
|
+ * take the spinlock since this is an optimization and nothing
|
|
|
+ * should get added until the cb counter goes to zero.
|
|
|
+ */
|
|
|
+ if (list_empty(&ls->ls_layouts))
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ /* Poll the client until it's done with the layout */
|
|
|
+ now = ktime_get();
|
|
|
+ nn = net_generic(ls->ls_stid.sc_client->net, nfsd_net_id);
|
|
|
+
|
|
|
+ /* Client gets 2 lease periods to return it */
|
|
|
+ cutoff = ktime_add_ns(task->tk_start,
|
|
|
+ nn->nfsd4_lease * NSEC_PER_SEC * 2);
|
|
|
+
|
|
|
+ if (ktime_before(now, cutoff)) {
|
|
|
+ rpc_delay(task, HZ/100); /* 10 mili-seconds */
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ /* Fallthrough */
|
|
|
case -NFS4ERR_NOMATCHING_LAYOUT:
|
|
|
trace_layout_recall_done(&ls->ls_stid.sc_stateid);
|
|
|
task->tk_status = 0;
|
|
|
return 1;
|
|
|
- case -NFS4ERR_DELAY:
|
|
|
- /* Poll the client until it's done with the layout */
|
|
|
- /* FIXME: cap number of retries.
|
|
|
- * The pnfs standard states that we need to only expire
|
|
|
- * the client after at-least "lease time" .eg lease-time * 2
|
|
|
- * when failing to communicate a recall
|
|
|
- */
|
|
|
- rpc_delay(task, HZ/100); /* 10 mili-seconds */
|
|
|
- return 0;
|
|
|
default:
|
|
|
/*
|
|
|
* Unknown error or non-responding client, we'll need to fence.
|