pNFS: Ensure we check layout segment validity in the pg_init() callback
authorTrond Myklebust <trond.myklebust@primarydata.com>
Tue, 25 Apr 2017 14:56:19 +0000 (10:56 -0400)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Tue, 25 Apr 2017 14:56:19 +0000 (10:56 -0400)
If we have a layout segment cached in pgio->pg_lseg, we should check it
for validity before reusing it in a new RPC request. Otherwise, if we
recoalesce, we can end up looping forever.

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

index acd30baca46166c902aa5dfae1663184cc30e235..d4174da89302b7ff7b60d4b601b1bcc5466a3f01 100644 (file)
@@ -933,6 +933,7 @@ static void
 filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio,
                        struct nfs_page *req)
 {
+       pnfs_generic_pg_check_layout(pgio);
        if (!pgio->pg_lseg) {
                pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode,
                                                      req->wb_context,
@@ -959,6 +960,7 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
        struct nfs_commit_info cinfo;
        int status;
 
+       pnfs_generic_pg_check_layout(pgio);
        if (!pgio->pg_lseg) {
                pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode,
                                                      req->wb_context,
index 42dedf2d625fca62a418c5e4f82935dc41a53987..f23b63eb356eab1f7d18ab1fad7f030f29a7e619 100644 (file)
@@ -846,6 +846,7 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
        int ds_idx;
 
 retry:
+       pnfs_generic_pg_check_layout(pgio);
        /* Use full layout for now */
        if (!pgio->pg_lseg)
                ff_layout_pg_get_read(pgio, req, false);
@@ -894,6 +895,7 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
        int status;
 
 retry:
+       pnfs_generic_pg_check_layout(pgio);
        if (!pgio->pg_lseg) {
                pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
                                                   req->wb_context,
index 3917a6272789d246eced76e0d24d022c96c8cb03..634adb3f85243f95d9509a87fa8cf58fb1f6b9b4 100644 (file)
@@ -2072,11 +2072,23 @@ void pnfs_error_mark_layout_for_return(struct inode *inode,
 }
 EXPORT_SYMBOL_GPL(pnfs_error_mark_layout_for_return);
 
+void
+pnfs_generic_pg_check_layout(struct nfs_pageio_descriptor *pgio)
+{
+       if (pgio->pg_lseg == NULL ||
+           test_bit(NFS_LSEG_VALID, &pgio->pg_lseg->pls_flags))
+               return;
+       pnfs_put_lseg(pgio->pg_lseg);
+       pgio->pg_lseg = NULL;
+}
+EXPORT_SYMBOL_GPL(pnfs_generic_pg_check_layout);
+
 void
 pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
 {
        u64 rd_size = req->wb_bytes;
 
+       pnfs_generic_pg_check_layout(pgio);
        if (pgio->pg_lseg == NULL) {
                if (pgio->pg_dreq == NULL)
                        rd_size = i_size_read(pgio->pg_inode) - req_offset(req);
@@ -2107,6 +2119,7 @@ void
 pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,
                           struct nfs_page *req, u64 wb_size)
 {
+       pnfs_generic_pg_check_layout(pgio);
        if (pgio->pg_lseg == NULL) {
                pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
                                                   req->wb_context,
index 825a1b8ddc4f9817813e64bab8b2eeaa4a048710..2d05b756a8d6504e79796d71eb5471a578d9ef5a 100644 (file)
@@ -234,6 +234,7 @@ void pnfs_put_lseg_locked(struct pnfs_layout_segment *lseg);
 
 void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, struct nfs_fsinfo *);
 void unset_pnfs_layoutdriver(struct nfs_server *);
+void pnfs_generic_pg_check_layout(struct nfs_pageio_descriptor *pgio);
 void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *);
 int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc);
 void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,