ds = nfs4_ff_layout_prepare_ds(lseg, idx, true);
        if (!ds)
-               return PNFS_NOT_ATTEMPTED;
+               goto out_failed;
 
        ds_clnt = nfs4_ff_find_or_create_ds_client(lseg, idx, ds->ds_clp,
                                                   hdr->inode);
        if (IS_ERR(ds_clnt))
-               return PNFS_NOT_ATTEMPTED;
+               goto out_failed;
 
        ds_cred = ff_layout_get_ds_cred(lseg, idx, hdr->cred);
        if (!ds_cred)
-               return PNFS_NOT_ATTEMPTED;
+               goto out_failed;
 
        vers = nfs4_ff_layout_ds_version(lseg, idx);
 
                          sync, RPC_TASK_SOFTCONN);
        put_rpccred(ds_cred);
        return PNFS_ATTEMPTED;
+
+out_failed:
+       if (ff_layout_avoid_mds_available_ds(lseg))
+               return PNFS_TRY_AGAIN;
+       return PNFS_NOT_ATTEMPTED;
 }
 
 static u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i)
 
        enum pnfs_try_status trypnfs;
 
        trypnfs = pnfs_try_to_write_data(hdr, call_ops, lseg, how);
-       if (trypnfs == PNFS_NOT_ATTEMPTED)
+       switch (trypnfs) {
+       case PNFS_NOT_ATTEMPTED:
                pnfs_write_through_mds(desc, hdr);
+       case PNFS_ATTEMPTED:
+               break;
+       case PNFS_TRY_AGAIN:
+               /* cleanup hdr and prepare to redo pnfs */
+               if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) {
+                       struct nfs_pgio_mirror *mirror = nfs_pgio_current_mirror(desc);
+                       list_splice_init(&hdr->pages, &mirror->pg_list);
+                       mirror->pg_recoalesce = 1;
+               }
+               hdr->mds_ops->rpc_release(hdr);
+       }
 }
 
 static void pnfs_writehdr_free(struct nfs_pgio_header *hdr)