NFSv4.1/flexfiles: Mark layout for return if the mirrors are invalid
authorTrond Myklebust <trond.myklebust@primarydata.com>
Tue, 1 Sep 2015 07:58:24 +0000 (00:58 -0700)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Tue, 1 Sep 2015 22:12:11 +0000 (15:12 -0700)
If a read-write layout has an invalid mirror, then we should
mark it as invalid, and return it.
If a read-only layout has an invalid mirror, then mark it as invalid
and check if there is still at least one valid mirror before we return
it.

Note: Also fix incorrect use of pnfs_generic_mark_devid_invalid().
We really want nfs4_mark_deviceid_unavailable().

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
fs/nfs/flexfilelayout/flexfilelayoutdev.c

index b6c21e9fa0026d23b984962ec3f3b66b5cb993c5..e125e55de86daebcbba9f2f907aca05fa27a0a1a 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;
-                       nfs4_mark_deviceid_unavailable(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;
-                       nfs4_mark_deviceid_unavailable(devid);
-               }
                goto out;
        }