]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - fs/nfsd/nfs4layouts.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile
[mirror_ubuntu-zesty-kernel.git] / fs / nfsd / nfs4layouts.c
index c9d6c715c0fb7e3187ffd1f2105f9527aa32259b..ce2d010d3b170627c82b281c11e206bd97109365 100644 (file)
@@ -22,7 +22,7 @@ struct nfs4_layout {
 static struct kmem_cache *nfs4_layout_cache;
 static struct kmem_cache *nfs4_layout_stateid_cache;
 
-static struct nfsd4_callback_ops nfsd4_cb_layout_ops;
+static const struct nfsd4_callback_ops nfsd4_cb_layout_ops;
 static const struct lock_manager_operations nfsd4_layouts_lm_ops;
 
 const struct nfsd4_layout_ops *nfsd4_layout_ops[LAYOUT_TYPE_MAX] =  {
@@ -624,24 +624,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.
@@ -665,7 +680,7 @@ nfsd4_cb_layout_release(struct nfsd4_callback *cb)
        nfs4_put_stid(&ls->ls_stid);
 }
 
-static struct nfsd4_callback_ops nfsd4_cb_layout_ops = {
+static const struct nfsd4_callback_ops nfsd4_cb_layout_ops = {
        .prepare        = nfsd4_cb_layout_prepare,
        .done           = nfsd4_cb_layout_done,
        .release        = nfsd4_cb_layout_release,