NFS41: pop some layoutget errors to application
authorPeng Tao <tao.peng@primarydata.com>
Thu, 3 Dec 2015 18:57:48 +0000 (02:57 +0800)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Mon, 28 Dec 2015 19:32:36 +0000 (14:32 -0500)
For ERESTARTSYS/EIO/EROFS/ENOSPC/E2BIG in layoutget, we
should just bail out instead of hiding the error and
retrying inband IO.

Change all the call sites to pop the error all the way up.

Signed-off-by: Peng Tao <tao.peng@primarydata.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
fs/nfs/direct.c
fs/nfs/filelayout/filelayout.c
fs/nfs/flexfilelayout/flexfilelayout.c
fs/nfs/pagelist.c
fs/nfs/pnfs.c
fs/nfs/read.c

index 4b1d08f56aba7940bf0872265902b2c793b05607..2e7142bcb4c83922748385c2d87771223e7cdc53 100644 (file)
@@ -670,6 +670,10 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
 
        req = nfs_list_entry(reqs.next);
        nfs_direct_setup_mirroring(dreq, &desc, req);
+       if (desc.pg_error < 0) {
+               list_splice_init(&reqs, &failed);
+               goto out_failed;
+       }
 
        list_for_each_entry_safe(req, tmp, &reqs, wb_list) {
                if (!nfs_pageio_add_request(&desc, req)) {
@@ -677,13 +681,17 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
                        nfs_list_add_request(req, &failed);
                        spin_lock(cinfo.lock);
                        dreq->flags = 0;
-                       dreq->error = -EIO;
+                       if (desc.pg_error < 0)
+                               dreq->error = desc.pg_error;
+                       else
+                               dreq->error = -EIO;
                        spin_unlock(cinfo.lock);
                }
                nfs_release_request(req);
        }
        nfs_pageio_complete(&desc);
 
+out_failed:
        while (!list_empty(&failed)) {
                req = nfs_list_entry(failed.next);
                nfs_list_remove_request(req);
@@ -900,6 +908,11 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
                        }
 
                        nfs_direct_setup_mirroring(dreq, &desc, req);
+                       if (desc.pg_error < 0) {
+                               nfs_free_request(req);
+                               result = desc.pg_error;
+                               break;
+                       }
 
                        nfs_lock_request(req);
                        req->wb_index = pos >> PAGE_SHIFT;
index 02ec07973bc43003bb76b5aaeb8a950094c9ac60..ae07b0f566591241a684e7ad49fc182159264041 100644 (file)
@@ -883,13 +883,19 @@ static void
 filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio,
                        struct nfs_page *req)
 {
-       if (!pgio->pg_lseg)
+       if (!pgio->pg_lseg) {
                pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
                                           req->wb_context,
                                           0,
                                           NFS4_MAX_UINT64,
                                           IOMODE_READ,
                                           GFP_KERNEL);
+               if (IS_ERR(pgio->pg_lseg)) {
+                       pgio->pg_error = PTR_ERR(pgio->pg_lseg);
+                       pgio->pg_lseg = NULL;
+                       return;
+               }
+       }
        /* If no lseg, fall back to read through mds */
        if (pgio->pg_lseg == NULL)
                nfs_pageio_reset_read_mds(pgio);
@@ -902,13 +908,20 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
        struct nfs_commit_info cinfo;
        int status;
 
-       if (!pgio->pg_lseg)
+       if (!pgio->pg_lseg) {
                pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
                                           req->wb_context,
                                           0,
                                           NFS4_MAX_UINT64,
                                           IOMODE_RW,
                                           GFP_NOFS);
+               if (IS_ERR(pgio->pg_lseg)) {
+                       pgio->pg_error = PTR_ERR(pgio->pg_lseg);
+                       pgio->pg_lseg = NULL;
+                       return;
+               }
+       }
+
        /* If no lseg, fall back to write through mds */
        if (pgio->pg_lseg == NULL)
                goto out_mds;
index 616817a464106b531c4291d1c8a1618a6f63fc75..57e4010e3cdebe9570cb4d5cdab6164599c18281 100644 (file)
@@ -795,13 +795,19 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
        int ds_idx;
 
        /* Use full layout for now */
-       if (!pgio->pg_lseg)
+       if (!pgio->pg_lseg) {
                pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
                                                   req->wb_context,
                                                   0,
                                                   NFS4_MAX_UINT64,
                                                   IOMODE_READ,
                                                   GFP_KERNEL);
+               if (IS_ERR(pgio->pg_lseg)) {
+                       pgio->pg_error = PTR_ERR(pgio->pg_lseg);
+                       pgio->pg_lseg = NULL;
+                       return;
+               }
+       }
        /* If no lseg, fall back to read through mds */
        if (pgio->pg_lseg == NULL)
                goto out_mds;
@@ -835,13 +841,19 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
        int i;
        int status;
 
-       if (!pgio->pg_lseg)
+       if (!pgio->pg_lseg) {
                pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
                                                   req->wb_context,
                                                   0,
                                                   NFS4_MAX_UINT64,
                                                   IOMODE_RW,
                                                   GFP_NOFS);
+               if (IS_ERR(pgio->pg_lseg)) {
+                       pgio->pg_error = PTR_ERR(pgio->pg_lseg);
+                       pgio->pg_lseg = NULL;
+                       return;
+               }
+       }
        /* If no lseg, fall back to write through mds */
        if (pgio->pg_lseg == NULL)
                goto out_mds;
@@ -877,18 +889,25 @@ static unsigned int
 ff_layout_pg_get_mirror_count_write(struct nfs_pageio_descriptor *pgio,
                                    struct nfs_page *req)
 {
-       if (!pgio->pg_lseg)
+       if (!pgio->pg_lseg) {
                pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
                                                   req->wb_context,
                                                   0,
                                                   NFS4_MAX_UINT64,
                                                   IOMODE_RW,
                                                   GFP_NOFS);
+               if (IS_ERR(pgio->pg_lseg)) {
+                       pgio->pg_error = PTR_ERR(pgio->pg_lseg);
+                       pgio->pg_lseg = NULL;
+                       goto out;
+               }
+       }
        if (pgio->pg_lseg)
                return FF_LAYOUT_MIRROR_COUNT(pgio->pg_lseg);
 
        /* no lseg means that pnfs is not in use, so no mirroring here */
        nfs_pageio_reset_write_mds(pgio);
+out:
        return 1;
 }
 
index 452a011ba0d8a33e9e4b9afd858f82858185f57e..728f65884cea5afaaecffebcbd18657c5e4aad1a 100644 (file)
@@ -874,6 +874,9 @@ static int nfs_pageio_setup_mirroring(struct nfs_pageio_descriptor *pgio,
 
        mirror_count = pgio->pg_ops->pg_get_mirror_count(pgio, req);
 
+       if (pgio->pg_error < 0)
+               return pgio->pg_error;
+
        if (!mirror_count || mirror_count > NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX)
                return -EINVAL;
 
@@ -982,6 +985,8 @@ static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc,
        } else {
                if (desc->pg_ops->pg_init)
                        desc->pg_ops->pg_init(desc, req);
+               if (desc->pg_error < 0)
+                       return 0;
                mirror->pg_base = req->wb_pgbase;
        }
        if (!nfs_can_coalesce_requests(prev, req, desc))
@@ -1147,6 +1152,8 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
        bytes = req->wb_bytes;
 
        nfs_pageio_setup_mirroring(desc, req);
+       if (desc->pg_error < 0)
+               return 0;
 
        for (midx = 0; midx < desc->pg_mirror_count; midx++) {
                if (midx) {
@@ -1232,7 +1239,7 @@ int nfs_pageio_resend(struct nfs_pageio_descriptor *desc,
        nfs_pageio_complete(desc);
        if (!list_empty(&failed)) {
                list_move(&failed, &hdr->pages);
-               return -EIO;
+               return desc->pg_error < 0 ? desc->pg_error : -EIO;
        }
        return 0;
 }
index 6095a8d42766c14fde2e199351ad1975a9776042..b1acc4135c3cb32c824ef419a9b4ba2193fd8d5f 100644 (file)
@@ -906,14 +906,15 @@ send_layoutget(struct pnfs_layout_hdr *lo,
 
        if (IS_ERR(lseg)) {
                switch (PTR_ERR(lseg)) {
-               case -ENOMEM:
                case -ERESTARTSYS:
+               case -EIO:
+               case -ENOSPC:
+               case -EROFS:
+               case -E2BIG:
                        break;
                default:
-                       /* remember that LAYOUTGET failed and suspend trying */
-                       pnfs_layout_io_set_failed(lo, range->iomode);
+                       return NULL;
                }
-               return NULL;
        } else
                pnfs_layout_clear_fail_bit(lo,
                                pnfs_iomode_to_fail_bit(range->iomode));
@@ -1649,7 +1650,7 @@ out:
                        "(%s, offset: %llu, length: %llu)\n",
                        __func__, ino->i_sb->s_id,
                        (unsigned long long)NFS_FILEID(ino),
-                       lseg == NULL ? "not found" : "found",
+                       IS_ERR_OR_NULL(lseg) ? "not found" : "found",
                        iomode==IOMODE_RW ?  "read/write" : "read-only",
                        (unsigned long long)pos,
                        (unsigned long long)count);
@@ -1828,6 +1829,11 @@ pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *r
                                                   rd_size,
                                                   IOMODE_READ,
                                                   GFP_KERNEL);
+               if (IS_ERR(pgio->pg_lseg)) {
+                       pgio->pg_error = PTR_ERR(pgio->pg_lseg);
+                       pgio->pg_lseg = NULL;
+                       return;
+               }
        }
        /* If no lseg, fall back to read through mds */
        if (pgio->pg_lseg == NULL)
@@ -1840,13 +1846,19 @@ void
 pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,
                           struct nfs_page *req, u64 wb_size)
 {
-       if (pgio->pg_lseg == NULL)
+       if (pgio->pg_lseg == NULL) {
                pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
                                                   req->wb_context,
                                                   req_offset(req),
                                                   wb_size,
                                                   IOMODE_RW,
                                                   GFP_NOFS);
+               if (IS_ERR(pgio->pg_lseg)) {
+                       pgio->pg_error = PTR_ERR(pgio->pg_lseg);
+                       pgio->pg_lseg = NULL;
+                       return;
+               }
+       }
        /* If no lseg, fall back to write through mds */
        if (pgio->pg_lseg == NULL)
                nfs_pageio_reset_write_mds(pgio);
index 0a5e33f33b5c83c73e69f1bab538bbb254175c16..0bb580174cb3d4b529c46bffaa4bb938ca3308b8 100644 (file)
@@ -115,7 +115,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
        pgm = &pgio.pg_mirrors[0];
        NFS_I(inode)->read_io += pgm->pg_bytes_written;
 
-       return 0;
+       return pgio.pg_error < 0 ? pgio.pg_error : 0;
 }
 
 static void nfs_readpage_release(struct nfs_page *req)