summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2015-12-31 09:28:06 -0500
committerTrond Myklebust <trond.myklebust@primarydata.com>2015-12-31 15:55:35 -0500
commitb20135d0b2431900a3a5395970ffb7e4f3767c8b (patch)
tree480ca93f19626e451cb79b35f29ad86d28da0fbb /fs
parentaf7cf057933f01dc7f33ddfb5e436ad598ed17ad (diff)
NFSv4.1/pNFS: Don't queue up a new commit if the layout segment is invalid
If the layout segment is invalid, then we should not be adding more write requests to the commit list. Instead, those writes should be replayed after requesting a new layout. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/callback_proc.c2
-rw-r--r--fs/nfs/direct.c12
-rw-r--r--fs/nfs/pnfs.c3
-rw-r--r--fs/nfs/pnfs.h6
-rw-r--r--fs/nfs/pnfs_nfs.c5
-rw-r--r--fs/nfs/write.c9
6 files changed, 37 insertions, 0 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index e4dbab5dce6e..2be8b252e3b1 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -233,6 +233,8 @@ static u32 initiate_file_draining(struct nfs_client *clp,
233unlock: 233unlock:
234 spin_unlock(&ino->i_lock); 234 spin_unlock(&ino->i_lock);
235 pnfs_free_lseg_list(&free_me_list); 235 pnfs_free_lseg_list(&free_me_list);
236 /* Free all lsegs that are attached to commit buckets */
237 nfs_commit_inode(ino, 0);
236 pnfs_put_layout_hdr(lo); 238 pnfs_put_layout_hdr(lo);
237 trace_nfs4_cb_layoutrecall_file(clp, &args->cbl_fh, ino, 239 trace_nfs4_cb_layoutrecall_file(clp, &args->cbl_fh, ino,
238 &args->cbl_stateid, -rv); 240 &args->cbl_stateid, -rv);
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 14f77df79c25..a9a93927fe3e 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -721,8 +721,20 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
721 nfs_direct_write_complete(dreq, data->inode); 721 nfs_direct_write_complete(dreq, data->inode);
722} 722}
723 723
724static void nfs_direct_resched_write(struct nfs_commit_info *cinfo,
725 struct nfs_page *req)
726{
727 struct nfs_direct_req *dreq = cinfo->dreq;
728
729 spin_lock(&dreq->lock);
730 dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
731 spin_unlock(&dreq->lock);
732 nfs_mark_request_commit(req, NULL, cinfo, 0);
733}
734
724static const struct nfs_commit_completion_ops nfs_direct_commit_completion_ops = { 735static const struct nfs_commit_completion_ops nfs_direct_commit_completion_ops = {
725 .completion = nfs_direct_commit_complete, 736 .completion = nfs_direct_commit_complete,
737 .resched_write = nfs_direct_resched_write,
726}; 738};
727 739
728static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) 740static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 360fe95c97b5..6593be7c0129 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -703,6 +703,8 @@ pnfs_layout_free_bulk_destroy_list(struct list_head *layout_list,
703 ret = -EAGAIN; 703 ret = -EAGAIN;
704 spin_unlock(&inode->i_lock); 704 spin_unlock(&inode->i_lock);
705 pnfs_free_lseg_list(&lseg_list); 705 pnfs_free_lseg_list(&lseg_list);
706 /* Free all lsegs that are attached to commit buckets */
707 nfs_commit_inode(inode, 0);
706 pnfs_put_layout_hdr(lo); 708 pnfs_put_layout_hdr(lo);
707 iput(inode); 709 iput(inode);
708 } 710 }
@@ -1811,6 +1813,7 @@ void pnfs_error_mark_layout_for_return(struct inode *inode,
1811 pnfs_mark_matching_lsegs_return(lo, &free_me, &range); 1813 pnfs_mark_matching_lsegs_return(lo, &free_me, &range);
1812 spin_unlock(&inode->i_lock); 1814 spin_unlock(&inode->i_lock);
1813 pnfs_free_lseg_list(&free_me); 1815 pnfs_free_lseg_list(&free_me);
1816 nfs_commit_inode(inode, 0);
1814} 1817}
1815EXPORT_SYMBOL_GPL(pnfs_error_mark_layout_for_return); 1818EXPORT_SYMBOL_GPL(pnfs_error_mark_layout_for_return);
1816 1819
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index d93c2ebc0fd3..4bd7faf9ce50 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -412,6 +412,12 @@ pnfs_get_lseg(struct pnfs_layout_segment *lseg)
412 return lseg; 412 return lseg;
413} 413}
414 414
415static inline bool
416pnfs_is_valid_lseg(struct pnfs_layout_segment *lseg)
417{
418 return test_bit(NFS_LSEG_VALID, &lseg->pls_flags) != 0;
419}
420
415/* Return true if a layout driver is being used for this mountpoint */ 421/* Return true if a layout driver is being used for this mountpoint */
416static inline int pnfs_enabled_sb(struct nfs_server *nfss) 422static inline int pnfs_enabled_sb(struct nfs_server *nfss)
417{ 423{
diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c
index 3c8e3a44e6ea..81ac6480f9e7 100644
--- a/fs/nfs/pnfs_nfs.c
+++ b/fs/nfs/pnfs_nfs.c
@@ -868,6 +868,11 @@ pnfs_layout_mark_request_commit(struct nfs_page *req,
868 buckets = cinfo->ds->buckets; 868 buckets = cinfo->ds->buckets;
869 list = &buckets[ds_commit_idx].written; 869 list = &buckets[ds_commit_idx].written;
870 if (list_empty(list)) { 870 if (list_empty(list)) {
871 if (!pnfs_is_valid_lseg(lseg)) {
872 spin_unlock(cinfo->lock);
873 cinfo->completion_ops->resched_write(cinfo, req);
874 return;
875 }
871 /* Non-empty buckets hold a reference on the lseg. That ref 876 /* Non-empty buckets hold a reference on the lseg. That ref
872 * is normally transferred to the COMMIT call and released 877 * is normally transferred to the COMMIT call and released
873 * there. It could also be released if the last req is pulled 878 * there. It could also be released if the last req is pulled
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index ae29f082c9c2..0aa8d6f23b4c 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1676,6 +1676,13 @@ void nfs_retry_commit(struct list_head *page_list,
1676} 1676}
1677EXPORT_SYMBOL_GPL(nfs_retry_commit); 1677EXPORT_SYMBOL_GPL(nfs_retry_commit);
1678 1678
1679static void
1680nfs_commit_resched_write(struct nfs_commit_info *cinfo,
1681 struct nfs_page *req)
1682{
1683 __set_page_dirty_nobuffers(req->wb_page);
1684}
1685
1679/* 1686/*
1680 * Commit dirty pages 1687 * Commit dirty pages
1681 */ 1688 */
@@ -1777,6 +1784,7 @@ static const struct rpc_call_ops nfs_commit_ops = {
1777 1784
1778static const struct nfs_commit_completion_ops nfs_commit_completion_ops = { 1785static const struct nfs_commit_completion_ops nfs_commit_completion_ops = {
1779 .completion = nfs_commit_release_pages, 1786 .completion = nfs_commit_release_pages,
1787 .resched_write = nfs_commit_resched_write,
1780}; 1788};
1781 1789
1782int nfs_generic_commit_list(struct inode *inode, struct list_head *head, 1790int nfs_generic_commit_list(struct inode *inode, struct list_head *head,
@@ -1823,6 +1831,7 @@ out_mark_dirty:
1823 __mark_inode_dirty(inode, I_DIRTY_DATASYNC); 1831 __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
1824 return res; 1832 return res;
1825} 1833}
1834EXPORT_SYMBOL_GPL(nfs_commit_inode);
1826 1835
1827int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) 1836int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
1828{ 1837{