These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / fs / nfs / flexfilelayout / flexfilelayoutdev.c
index b28fa4c..e125e55 100644 (file)
@@ -172,6 +172,32 @@ out_err:
        return NULL;
 }
 
+static void ff_layout_mark_devid_invalid(struct pnfs_layout_segment *lseg,
+               struct nfs4_deviceid_node *devid)
+{
+       nfs4_mark_deviceid_unavailable(devid);
+       if (!ff_layout_has_available_ds(lseg))
+               pnfs_error_mark_layout_for_return(lseg->pls_layout->plh_inode,
+                               lseg);
+}
+
+static bool ff_layout_mirror_valid(struct pnfs_layout_segment *lseg,
+               struct nfs4_ff_layout_mirror *mirror)
+{
+       if (mirror == NULL || mirror->mirror_ds == NULL) {
+               pnfs_error_mark_layout_for_return(lseg->pls_layout->plh_inode,
+                                       lseg);
+               return false;
+       }
+       if (mirror->mirror_ds->ds == NULL) {
+               struct nfs4_deviceid_node *devid;
+               devid = &mirror->mirror_ds->id_node;
+               ff_layout_mark_devid_invalid(lseg, devid);
+               return false;
+       }
+       return true;
+}
+
 static u64
 end_offset(u64 start, u64 len)
 {
@@ -336,16 +362,10 @@ nfs4_ff_layout_select_ds_fh(struct pnfs_layout_segment *lseg, u32 mirror_idx)
 {
        struct nfs4_ff_layout_mirror *mirror = FF_LAYOUT_COMP(lseg, mirror_idx);
        struct nfs_fh *fh = NULL;
-       struct nfs4_deviceid_node *devid;
 
-       if (mirror == NULL || mirror->mirror_ds == NULL ||
-           mirror->mirror_ds->ds == NULL) {
-               printk(KERN_ERR "NFS: %s: No data server for mirror offset index %d\n",
+       if (!ff_layout_mirror_valid(lseg, mirror)) {
+               pr_err_ratelimited("NFS: %s: No data server for mirror offset index %d\n",
                        __func__, mirror_idx);
-               if (mirror && mirror->mirror_ds) {
-                       devid = &mirror->mirror_ds->id_node;
-                       pnfs_generic_mark_devid_invalid(devid);
-               }
                goto out;
        }
 
@@ -368,14 +388,9 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
        unsigned int max_payload;
        rpc_authflavor_t flavor;
 
-       if (mirror == NULL || mirror->mirror_ds == NULL ||
-           mirror->mirror_ds->ds == NULL) {
-               printk(KERN_ERR "NFS: %s: No data server for offset index %d\n",
+       if (!ff_layout_mirror_valid(lseg, mirror)) {
+               pr_err_ratelimited("NFS: %s: No data server for offset index %d\n",
                        __func__, ds_idx);
-               if (mirror && mirror->mirror_ds) {
-                       devid = &mirror->mirror_ds->id_node;
-                       pnfs_generic_mark_devid_invalid(devid);
-               }
                goto out;
        }
 
@@ -528,11 +543,11 @@ int ff_layout_encode_ds_ioerr(struct nfs4_flexfile_layout *flo,
        return 0;
 }
 
-bool ff_layout_has_available_ds(struct pnfs_layout_segment *lseg)
+static bool ff_read_layout_has_available_ds(struct pnfs_layout_segment *lseg)
 {
        struct nfs4_ff_layout_mirror *mirror;
        struct nfs4_deviceid_node *devid;
-       int idx;
+       u32 idx;
 
        for (idx = 0; idx < FF_LAYOUT_MIRROR_COUNT(lseg); idx++) {
                mirror = FF_LAYOUT_COMP(lseg, idx);
@@ -546,6 +561,32 @@ bool ff_layout_has_available_ds(struct pnfs_layout_segment *lseg)
        return false;
 }
 
+static bool ff_rw_layout_has_available_ds(struct pnfs_layout_segment *lseg)
+{
+       struct nfs4_ff_layout_mirror *mirror;
+       struct nfs4_deviceid_node *devid;
+       u32 idx;
+
+       for (idx = 0; idx < FF_LAYOUT_MIRROR_COUNT(lseg); idx++) {
+               mirror = FF_LAYOUT_COMP(lseg, idx);
+               if (!mirror || !mirror->mirror_ds)
+                       return false;
+               devid = &mirror->mirror_ds->id_node;
+               if (ff_layout_test_devid_unavailable(devid))
+                       return false;
+       }
+
+       return FF_LAYOUT_MIRROR_COUNT(lseg) != 0;
+}
+
+bool ff_layout_has_available_ds(struct pnfs_layout_segment *lseg)
+{
+       if (lseg->pls_range.iomode == IOMODE_READ)
+               return  ff_read_layout_has_available_ds(lseg);
+       /* Note: RW layout needs all mirrors available */
+       return ff_rw_layout_has_available_ds(lseg);
+}
+
 module_param(dataserver_retrans, uint, 0644);
 MODULE_PARM_DESC(dataserver_retrans, "The  number of times the NFSv4.1 client "
                        "retries a request before it attempts further "