nfs41: add a helper function to set layoutcommit after commit
authorPeng Tao <tao.peng@primarydata.com>
Thu, 7 Aug 2014 02:15:02 +0000 (10:15 +0800)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Wed, 10 Sep 2014 19:47:00 +0000 (12:47 -0700)
Track lwb in nfs_commit_data so that we can use it to setup
layoutcommit in commit_done callback.

Signed-off-by: Peng Tao <tao.peng@primarydata.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/write.c
include/linux/nfs_xdr.h

index a3851debf8a2f481435b3750f5cb1bec678ab4fe..a6586cdee2110780796abaf3af017f4b8a2b94e7 100644 (file)
@@ -1797,6 +1797,35 @@ pnfs_set_layoutcommit(struct nfs_pgio_header *hdr)
 }
 EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit);
 
+void pnfs_commit_set_layoutcommit(struct nfs_commit_data *data)
+{
+       struct inode *inode = data->inode;
+       struct nfs_inode *nfsi = NFS_I(inode);
+       bool mark_as_dirty = false;
+
+       spin_lock(&inode->i_lock);
+       if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
+               mark_as_dirty = true;
+               dprintk("%s: Set layoutcommit for inode %lu ",
+                       __func__, inode->i_ino);
+       }
+       if (!test_and_set_bit(NFS_LSEG_LAYOUTCOMMIT, &data->lseg->pls_flags)) {
+               /* references matched in nfs4_layoutcommit_release */
+               pnfs_get_lseg(data->lseg);
+       }
+       if (data->lwb > nfsi->layout->plh_lwb)
+               nfsi->layout->plh_lwb = data->lwb;
+       spin_unlock(&inode->i_lock);
+       dprintk("%s: lseg %p end_pos %llu\n",
+               __func__, data->lseg, nfsi->layout->plh_lwb);
+
+       /* if pnfs_layoutcommit_inode() runs between inode locks, the next one
+        * will be a noop because NFS_INO_LAYOUTCOMMIT will not be set */
+       if (mark_as_dirty)
+               mark_inode_dirty_sync(inode);
+}
+EXPORT_SYMBOL_GPL(pnfs_commit_set_layoutcommit);
+
 void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data)
 {
        struct nfs_server *nfss = NFS_SERVER(data->args.inode);
index aca3dff5dae63e3a5d41f3e43b7055e77372b841..79c63114ce775484f50efc6f3888b1f8649773d9 100644 (file)
@@ -219,6 +219,7 @@ void pnfs_roc_release(struct inode *ino);
 void pnfs_roc_set_barrier(struct inode *ino, u32 barrier);
 bool pnfs_roc_drain(struct inode *ino, u32 *barrier, struct rpc_task *task);
 void pnfs_set_layoutcommit(struct nfs_pgio_header *);
+void pnfs_commit_set_layoutcommit(struct nfs_commit_data *data);
 void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data);
 int pnfs_layoutcommit_inode(struct inode *inode, bool sync);
 int _pnfs_return_layout(struct inode *);
index 175d5d073ccf350db485daf81ab3030555d80a60..3c5638f381cdba03bd3607f4caf5490d9a765c6a 100644 (file)
@@ -1538,6 +1538,18 @@ int nfs_initiate_commit(struct rpc_clnt *clnt, struct nfs_commit_data *data,
 }
 EXPORT_SYMBOL_GPL(nfs_initiate_commit);
 
+static loff_t nfs_get_lwb(struct list_head *head)
+{
+       loff_t lwb = 0;
+       struct nfs_page *req;
+
+       list_for_each_entry(req, head, wb_list)
+               if (lwb < (req_offset(req) + req->wb_bytes))
+                       lwb = req_offset(req) + req->wb_bytes;
+
+       return lwb;
+}
+
 /*
  * Set up the argument/result storage required for the RPC call.
  */
@@ -1557,6 +1569,9 @@ void nfs_init_commit(struct nfs_commit_data *data,
        data->inode       = inode;
        data->cred        = first->wb_context->cred;
        data->lseg        = lseg; /* reference transferred */
+       /* only set lwb for pnfs commit */
+       if (lseg)
+               data->lwb = nfs_get_lwb(&data->pages);
        data->mds_ops     = &nfs_commit_ops;
        data->completion_ops = cinfo->completion_ops;
        data->dreq        = cinfo->dreq;
index 0040629894dfa42084161124edb2f494df5be4ea..e563b2c976ef48bdfd397792920f8ff7e4db4f6e 100644 (file)
@@ -1328,6 +1328,7 @@ struct nfs_commit_data {
        struct pnfs_layout_segment *lseg;
        struct nfs_client       *ds_clp;        /* pNFS data server */
        int                     ds_commit_index;
+       loff_t                  lwb;
        const struct rpc_call_ops *mds_ops;
        const struct nfs_commit_completion_ops *completion_ops;
        int (*commit_done_cb) (struct rpc_task *task, struct nfs_commit_data *data);