genirq: Dont allow affinity mask to be updated on IPIs
[deliverable/linux.git] / fs / nfsd / nfs4layouts.c
index c9d6c715c0fb7e3187ffd1f2105f9527aa32259b..825c7bc8d789716749138583953c26e630294a93 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2014 Christoph Hellwig.
  */
+#include <linux/blkdev.h>
 #include <linux/kmod.h>
 #include <linux/file.h>
 #include <linux/jhash.h>
@@ -22,11 +23,16 @@ 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] =  {
+#ifdef CONFIG_NFSD_BLOCKLAYOUT
        [LAYOUT_BLOCK_VOLUME]   = &bl_layout_ops,
+#endif
+#ifdef CONFIG_NFSD_SCSILAYOUT
+       [LAYOUT_SCSI]           = &scsi_layout_ops,
+#endif
 };
 
 /* pNFS device ID to export fsid mapping */
@@ -121,10 +127,24 @@ void nfsd4_setup_layout_type(struct svc_export *exp)
        if (!(exp->ex_flags & NFSEXP_PNFS))
                return;
 
+       /*
+        * Check if the file system supports exporting a block-like layout.
+        * If the block device supports reservations prefer the SCSI layout,
+        * otherwise advertise the block layout.
+        */
+#ifdef CONFIG_NFSD_BLOCKLAYOUT
        if (sb->s_export_op->get_uuid &&
            sb->s_export_op->map_blocks &&
            sb->s_export_op->commit_blocks)
                exp->ex_layout_type = LAYOUT_BLOCK_VOLUME;
+#endif
+#ifdef CONFIG_NFSD_SCSILAYOUT
+       /* overwrite block layout selection if needed */
+       if (sb->s_export_op->map_blocks &&
+           sb->s_export_op->commit_blocks &&
+           sb->s_bdev && sb->s_bdev->bd_disk->fops->pr_ops)
+               exp->ex_layout_type = LAYOUT_SCSI;
+#endif
 }
 
 static void
@@ -590,8 +610,6 @@ nfsd4_cb_layout_fail(struct nfs4_layout_stateid *ls)
 
        rpc_ntop((struct sockaddr *)&clp->cl_addr, addr_str, sizeof(addr_str));
 
-       trace_layout_recall_fail(&ls->ls_stid.sc_stateid);
-
        printk(KERN_WARNING
                "nfsd: client %s failed to respond to layout recall. "
                "  Fencing..\n", addr_str);
@@ -624,29 +642,51 @@ 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;
+       const struct nfsd4_layout_ops *ops;
        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.
                 */
-               nfsd4_cb_layout_fail(ls);
+               trace_layout_recall_fail(&ls->ls_stid.sc_stateid);
+
+               ops = nfsd4_layout_ops[ls->ls_layout_type];
+               if (ops->fence_client)
+                       ops->fence_client(ls);
+               else
+                       nfsd4_cb_layout_fail(ls);
                return -1;
        }
 }
@@ -665,7 +705,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,
This page took 0.027512 seconds and 5 git commands to generate.