aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAndy Adamson <andros@netapp.com>2011-03-23 09:27:54 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-03-23 15:29:04 -0400
commit863a3c6c686d5773f7192a4818769e15db12ce08 (patch)
tree3ff8bf04c583aa0c16ae30b0821bc9148d49a47a /fs
parente0c2b3801828aadb65dec9f67f7c6b7a675ad007 (diff)
NFSv4.1: layoutcommit
The filelayout driver sends LAYOUTCOMMIT only when COMMIT goes to the data server (as opposed to the MDS) and the data server WRITE is not NFS_FILE_SYNC. Only whole file layout support means that there is only one IOMODE_RW layout segment. Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Alexandros Batsakis <batsakis@netapp.com> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: Dean Hildebrand <dhildeb@us.ibm.com> Signed-off-by: Fred Isaman <iisaman@citi.umich.edu> Signed-off-by: Mingyang Guo <guomingyang@nrchpc.ac.cn> Signed-off-by: Tao Guo <guotao@nrchpc.ac.cn> Signed-off-by: Zhang Jingwang <zhangjingwang@nrchpc.ac.cn> Tested-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> Signed-off-by: Fred Isaman <iisaman@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/file.c3
-rw-r--r--fs/nfs/nfs4_fs.h2
-rw-r--r--fs/nfs/nfs4filelayout.c18
-rw-r--r--fs/nfs/nfs4proc.c94
-rw-r--r--fs/nfs/nfs4xdr.c129
-rw-r--r--fs/nfs/pnfs.c94
-rw-r--r--fs/nfs/pnfs.h9
-rw-r--r--fs/nfs/write.c15
8 files changed, 362 insertions, 2 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index d85a534b15cd..85cb95de5df5 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -326,6 +326,9 @@ nfs_file_fsync(struct file *file, int datasync)
326 ret = xchg(&ctx->error, 0); 326 ret = xchg(&ctx->error, 0);
327 if (!ret && status < 0) 327 if (!ret && status < 0)
328 ret = status; 328 ret = status;
329 if (!ret && !datasync)
330 /* application has asked for meta-data sync */
331 ret = pnfs_layoutcommit_inode(inode, 1);
329 return ret; 332 return ret;
330} 333}
331 334
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index c64be1cff080..1e612d159b71 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -262,6 +262,8 @@ extern int nfs4_proc_destroy_session(struct nfs4_session *);
262extern int nfs4_init_session(struct nfs_server *server); 262extern int nfs4_init_session(struct nfs_server *server);
263extern int nfs4_proc_get_lease_time(struct nfs_client *clp, 263extern int nfs4_proc_get_lease_time(struct nfs_client *clp,
264 struct nfs_fsinfo *fsinfo); 264 struct nfs_fsinfo *fsinfo);
265extern int nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data,
266 int sync);
265 267
266static inline bool 268static inline bool
267is_ds_only_client(struct nfs_client *clp) 269is_ds_only_client(struct nfs_client *clp)
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index 97e75a22af72..fc1a0e9c1270 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -154,6 +154,23 @@ static int filelayout_read_done_cb(struct rpc_task *task,
154} 154}
155 155
156/* 156/*
157 * We reference the rpc_cred of the first WRITE that triggers the need for
158 * a LAYOUTCOMMIT, and use it to send the layoutcommit compound.
159 * rfc5661 is not clear about which credential should be used.
160 */
161static void
162filelayout_set_layoutcommit(struct nfs_write_data *wdata)
163{
164 if (FILELAYOUT_LSEG(wdata->lseg)->commit_through_mds ||
165 wdata->res.verf->committed == NFS_FILE_SYNC)
166 return;
167
168 pnfs_set_layoutcommit(wdata);
169 dprintk("%s ionde %lu pls_end_pos %lu\n", __func__, wdata->inode->i_ino,
170 (unsigned long) wdata->lseg->pls_end_pos);
171}
172
173/*
157 * Call ops for the async read/write cases 174 * Call ops for the async read/write cases
158 * In the case of dense layouts, the offset needs to be reset to its 175 * In the case of dense layouts, the offset needs to be reset to its
159 * original value. 176 * original value.
@@ -210,6 +227,7 @@ static int filelayout_write_done_cb(struct rpc_task *task,
210 return -EAGAIN; 227 return -EAGAIN;
211 } 228 }
212 229
230 filelayout_set_layoutcommit(data);
213 return 0; 231 return 0;
214} 232}
215 233
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 5d61cccc8d4d..6f2f40239d10 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -5616,6 +5616,100 @@ int nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev)
5616} 5616}
5617EXPORT_SYMBOL_GPL(nfs4_proc_getdeviceinfo); 5617EXPORT_SYMBOL_GPL(nfs4_proc_getdeviceinfo);
5618 5618
5619static void nfs4_layoutcommit_prepare(struct rpc_task *task, void *calldata)
5620{
5621 struct nfs4_layoutcommit_data *data = calldata;
5622 struct nfs_server *server = NFS_SERVER(data->args.inode);
5623
5624 if (nfs4_setup_sequence(server, &data->args.seq_args,
5625 &data->res.seq_res, 1, task))
5626 return;
5627 rpc_call_start(task);
5628}
5629
5630static void
5631nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
5632{
5633 struct nfs4_layoutcommit_data *data = calldata;
5634 struct nfs_server *server = NFS_SERVER(data->args.inode);
5635
5636 if (!nfs4_sequence_done(task, &data->res.seq_res))
5637 return;
5638
5639 switch (task->tk_status) { /* Just ignore these failures */
5640 case NFS4ERR_DELEG_REVOKED: /* layout was recalled */
5641 case NFS4ERR_BADIOMODE: /* no IOMODE_RW layout for range */
5642 case NFS4ERR_BADLAYOUT: /* no layout */
5643 case NFS4ERR_GRACE: /* loca_recalim always false */
5644 task->tk_status = 0;
5645 }
5646
5647 if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) {
5648 nfs_restart_rpc(task, server->nfs_client);
5649 return;
5650 }
5651
5652 if (task->tk_status == 0)
5653 nfs_post_op_update_inode_force_wcc(data->args.inode,
5654 data->res.fattr);
5655}
5656
5657static void nfs4_layoutcommit_release(void *calldata)
5658{
5659 struct nfs4_layoutcommit_data *data = calldata;
5660
5661 /* Matched by references in pnfs_set_layoutcommit */
5662 put_lseg(data->lseg);
5663 put_rpccred(data->cred);
5664 kfree(data);
5665}
5666
5667static const struct rpc_call_ops nfs4_layoutcommit_ops = {
5668 .rpc_call_prepare = nfs4_layoutcommit_prepare,
5669 .rpc_call_done = nfs4_layoutcommit_done,
5670 .rpc_release = nfs4_layoutcommit_release,
5671};
5672
5673int
5674nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, int sync)
5675{
5676 struct rpc_message msg = {
5677 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTCOMMIT],
5678 .rpc_argp = &data->args,
5679 .rpc_resp = &data->res,
5680 .rpc_cred = data->cred,
5681 };
5682 struct rpc_task_setup task_setup_data = {
5683 .task = &data->task,
5684 .rpc_client = NFS_CLIENT(data->args.inode),
5685 .rpc_message = &msg,
5686 .callback_ops = &nfs4_layoutcommit_ops,
5687 .callback_data = data,
5688 .flags = RPC_TASK_ASYNC,
5689 };
5690 struct rpc_task *task;
5691 int status = 0;
5692
5693 dprintk("NFS: %4d initiating layoutcommit call. sync %d "
5694 "lbw: %llu inode %lu\n",
5695 data->task.tk_pid, sync,
5696 data->args.lastbytewritten,
5697 data->args.inode->i_ino);
5698
5699 task = rpc_run_task(&task_setup_data);
5700 if (IS_ERR(task))
5701 return PTR_ERR(task);
5702 if (!sync)
5703 goto out;
5704 status = nfs4_wait_for_completion_rpc_task(task);
5705 if (status != 0)
5706 goto out;
5707 status = task->tk_status;
5708out:
5709 dprintk("%s: status %d\n", __func__, status);
5710 rpc_put_task(task);
5711 return status;
5712}
5619#endif /* CONFIG_NFS_V4_1 */ 5713#endif /* CONFIG_NFS_V4_1 */
5620 5714
5621struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { 5715struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 07cdf925c524..207d399c8dee 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -324,6 +324,18 @@ static int nfs4_stat_to_errno(int);
324#define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \ 324#define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \
325 decode_stateid_maxsz + \ 325 decode_stateid_maxsz + \
326 XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE)) 326 XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE))
327#define encode_layoutcommit_maxsz (op_encode_hdr_maxsz + \
328 2 /* offset */ + \
329 2 /* length */ + \
330 1 /* reclaim */ + \
331 encode_stateid_maxsz + \
332 1 /* new offset (true) */ + \
333 2 /* last byte written */ + \
334 1 /* nt_timechanged (false) */ + \
335 1 /* layoutupdate4 layout type */ + \
336 1 /* NULL filelayout layoutupdate4 payload */)
337#define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3)
338
327#else /* CONFIG_NFS_V4_1 */ 339#else /* CONFIG_NFS_V4_1 */
328#define encode_sequence_maxsz 0 340#define encode_sequence_maxsz 0
329#define decode_sequence_maxsz 0 341#define decode_sequence_maxsz 0
@@ -727,6 +739,17 @@ static int nfs4_stat_to_errno(int);
727 decode_sequence_maxsz + \ 739 decode_sequence_maxsz + \
728 decode_putfh_maxsz + \ 740 decode_putfh_maxsz + \
729 decode_layoutget_maxsz) 741 decode_layoutget_maxsz)
742#define NFS4_enc_layoutcommit_sz (compound_encode_hdr_maxsz + \
743 encode_sequence_maxsz +\
744 encode_putfh_maxsz + \
745 encode_layoutcommit_maxsz + \
746 encode_getattr_maxsz)
747#define NFS4_dec_layoutcommit_sz (compound_decode_hdr_maxsz + \
748 decode_sequence_maxsz + \
749 decode_putfh_maxsz + \
750 decode_layoutcommit_maxsz + \
751 decode_getattr_maxsz)
752
730 753
731const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + 754const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
732 compound_encode_hdr_maxsz + 755 compound_encode_hdr_maxsz +
@@ -1816,6 +1839,34 @@ encode_layoutget(struct xdr_stream *xdr,
1816 hdr->nops++; 1839 hdr->nops++;
1817 hdr->replen += decode_layoutget_maxsz; 1840 hdr->replen += decode_layoutget_maxsz;
1818} 1841}
1842
1843static int
1844encode_layoutcommit(struct xdr_stream *xdr,
1845 const struct nfs4_layoutcommit_args *args,
1846 struct compound_hdr *hdr)
1847{
1848 __be32 *p;
1849
1850 dprintk("%s: lbw: %llu type: %d\n", __func__, args->lastbytewritten,
1851 NFS_SERVER(args->inode)->pnfs_curr_ld->id);
1852
1853 p = reserve_space(xdr, 48 + NFS4_STATEID_SIZE);
1854 *p++ = cpu_to_be32(OP_LAYOUTCOMMIT);
1855 /* Only whole file layouts */
1856 p = xdr_encode_hyper(p, 0); /* offset */
1857 p = xdr_encode_hyper(p, NFS4_MAX_UINT64); /* length */
1858 *p++ = cpu_to_be32(0); /* reclaim */
1859 p = xdr_encode_opaque_fixed(p, args->stateid.data, NFS4_STATEID_SIZE);
1860 *p++ = cpu_to_be32(1); /* newoffset = TRUE */
1861 p = xdr_encode_hyper(p, args->lastbytewritten);
1862 *p++ = cpu_to_be32(0); /* Never send time_modify_changed */
1863 *p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */
1864 *p++ = cpu_to_be32(0); /* no file layout payload */
1865
1866 hdr->nops++;
1867 hdr->replen += decode_layoutcommit_maxsz;
1868 return 0;
1869}
1819#endif /* CONFIG_NFS_V4_1 */ 1870#endif /* CONFIG_NFS_V4_1 */
1820 1871
1821/* 1872/*
@@ -2607,6 +2658,26 @@ static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req,
2607 encode_layoutget(xdr, args, &hdr); 2658 encode_layoutget(xdr, args, &hdr);
2608 encode_nops(&hdr); 2659 encode_nops(&hdr);
2609} 2660}
2661
2662/*
2663 * Encode LAYOUTCOMMIT request
2664 */
2665static int nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req,
2666 struct xdr_stream *xdr,
2667 struct nfs4_layoutcommit_args *args)
2668{
2669 struct compound_hdr hdr = {
2670 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2671 };
2672
2673 encode_compound_hdr(xdr, req, &hdr);
2674 encode_sequence(xdr, &args->seq_args, &hdr);
2675 encode_putfh(xdr, NFS_FH(args->inode), &hdr);
2676 encode_layoutcommit(xdr, args, &hdr);
2677 encode_getfattr(xdr, args->bitmask, &hdr);
2678 encode_nops(&hdr);
2679 return 0;
2680}
2610#endif /* CONFIG_NFS_V4_1 */ 2681#endif /* CONFIG_NFS_V4_1 */
2611 2682
2612static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) 2683static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
@@ -5007,6 +5078,35 @@ out_overflow:
5007 print_overflow_msg(__func__, xdr); 5078 print_overflow_msg(__func__, xdr);
5008 return -EIO; 5079 return -EIO;
5009} 5080}
5081
5082static int decode_layoutcommit(struct xdr_stream *xdr,
5083 struct rpc_rqst *req,
5084 struct nfs4_layoutcommit_res *res)
5085{
5086 __be32 *p;
5087 __u32 sizechanged;
5088 int status;
5089
5090 status = decode_op_hdr(xdr, OP_LAYOUTCOMMIT);
5091 if (status)
5092 return status;
5093
5094 p = xdr_inline_decode(xdr, 4);
5095 if (unlikely(!p))
5096 goto out_overflow;
5097 sizechanged = be32_to_cpup(p);
5098
5099 if (sizechanged) {
5100 /* throw away new size */
5101 p = xdr_inline_decode(xdr, 8);
5102 if (unlikely(!p))
5103 goto out_overflow;
5104 }
5105 return 0;
5106out_overflow:
5107 print_overflow_msg(__func__, xdr);
5108 return -EIO;
5109}
5010#endif /* CONFIG_NFS_V4_1 */ 5110#endif /* CONFIG_NFS_V4_1 */
5011 5111
5012/* 5112/*
@@ -6068,6 +6168,34 @@ static int nfs4_xdr_dec_layoutget(struct rpc_rqst *rqstp,
6068out: 6168out:
6069 return status; 6169 return status;
6070} 6170}
6171
6172/*
6173 * Decode LAYOUTCOMMIT response
6174 */
6175static int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp,
6176 struct xdr_stream *xdr,
6177 struct nfs4_layoutcommit_res *res)
6178{
6179 struct compound_hdr hdr;
6180 int status;
6181
6182 status = decode_compound_hdr(xdr, &hdr);
6183 if (status)
6184 goto out;
6185 status = decode_sequence(xdr, &res->seq_res, rqstp);
6186 if (status)
6187 goto out;
6188 status = decode_putfh(xdr);
6189 if (status)
6190 goto out;
6191 status = decode_layoutcommit(xdr, rqstp, res);
6192 if (status)
6193 goto out;
6194 decode_getfattr(xdr, res->fattr, res->server,
6195 !RPC_IS_ASYNC(rqstp->rq_task));
6196out:
6197 return status;
6198}
6071#endif /* CONFIG_NFS_V4_1 */ 6199#endif /* CONFIG_NFS_V4_1 */
6072 6200
6073/** 6201/**
@@ -6269,6 +6397,7 @@ struct rpc_procinfo nfs4_procedures[] = {
6269 PROC(RECLAIM_COMPLETE, enc_reclaim_complete, dec_reclaim_complete), 6397 PROC(RECLAIM_COMPLETE, enc_reclaim_complete, dec_reclaim_complete),
6270 PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo), 6398 PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo),
6271 PROC(LAYOUTGET, enc_layoutget, dec_layoutget), 6399 PROC(LAYOUTGET, enc_layoutget, dec_layoutget),
6400 PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit),
6272#endif /* CONFIG_NFS_V4_1 */ 6401#endif /* CONFIG_NFS_V4_1 */
6273}; 6402};
6274 6403
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index c67565965f2a..2a08ca0dddc1 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -946,3 +946,97 @@ pnfs_try_to_read_data(struct nfs_read_data *rdata,
946 dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs); 946 dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs);
947 return trypnfs; 947 return trypnfs;
948} 948}
949
950/*
951 * Currently there is only one (whole file) write lseg.
952 */
953static struct pnfs_layout_segment *pnfs_list_write_lseg(struct inode *inode)
954{
955 struct pnfs_layout_segment *lseg, *rv = NULL;
956
957 list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list)
958 if (lseg->pls_range.iomode == IOMODE_RW)
959 rv = lseg;
960 return rv;
961}
962
963void
964pnfs_set_layoutcommit(struct nfs_write_data *wdata)
965{
966 struct nfs_inode *nfsi = NFS_I(wdata->inode);
967 loff_t end_pos = wdata->args.offset + wdata->res.count;
968
969 spin_lock(&nfsi->vfs_inode.i_lock);
970 if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
971 /* references matched in nfs4_layoutcommit_release */
972 get_lseg(wdata->lseg);
973 wdata->lseg->pls_lc_cred =
974 get_rpccred(wdata->args.context->state->owner->so_cred);
975 mark_inode_dirty_sync(wdata->inode);
976 dprintk("%s: Set layoutcommit for inode %lu ",
977 __func__, wdata->inode->i_ino);
978 }
979 if (end_pos > wdata->lseg->pls_end_pos)
980 wdata->lseg->pls_end_pos = end_pos;
981 spin_unlock(&nfsi->vfs_inode.i_lock);
982}
983EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit);
984
985int
986pnfs_layoutcommit_inode(struct inode *inode, int sync)
987{
988 struct nfs4_layoutcommit_data *data;
989 struct nfs_inode *nfsi = NFS_I(inode);
990 struct pnfs_layout_segment *lseg;
991 struct rpc_cred *cred;
992 loff_t end_pos;
993 int status = 0;
994
995 dprintk("--> %s inode %lu\n", __func__, inode->i_ino);
996
997 /* Note kzalloc ensures data->res.seq_res.sr_slot == NULL */
998 data = kzalloc(sizeof(*data), GFP_NOFS);
999 spin_lock(&inode->i_lock);
1000
1001 if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
1002 spin_unlock(&inode->i_lock);
1003 kfree(data);
1004 goto out;
1005 }
1006 /*
1007 * Currently only one (whole file) write lseg which is referenced
1008 * in pnfs_set_layoutcommit and will be found.
1009 */
1010 lseg = pnfs_list_write_lseg(inode);
1011
1012 end_pos = lseg->pls_end_pos;
1013 cred = lseg->pls_lc_cred;
1014 lseg->pls_end_pos = 0;
1015 lseg->pls_lc_cred = NULL;
1016
1017 if (!data) {
1018 put_lseg(lseg);
1019 spin_unlock(&inode->i_lock);
1020 put_rpccred(cred);
1021 status = -ENOMEM;
1022 goto out;
1023 } else {
1024 memcpy(&data->args.stateid.data, nfsi->layout->plh_stateid.data,
1025 sizeof(nfsi->layout->plh_stateid.data));
1026 }
1027 spin_unlock(&inode->i_lock);
1028
1029 data->args.inode = inode;
1030 data->lseg = lseg;
1031 data->cred = cred;
1032 nfs_fattr_init(&data->fattr);
1033 data->args.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask;
1034 data->res.fattr = &data->fattr;
1035 data->args.lastbytewritten = end_pos - 1;
1036 data->res.server = NFS_SERVER(inode);
1037
1038 status = nfs4_proc_layoutcommit(data, sync);
1039out:
1040 dprintk("<-- %s status %d\n", __func__, status);
1041 return status;
1042}
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 5370f1b9aa43..0806c77862b6 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -43,6 +43,8 @@ struct pnfs_layout_segment {
43 atomic_t pls_refcount; 43 atomic_t pls_refcount;
44 unsigned long pls_flags; 44 unsigned long pls_flags;
45 struct pnfs_layout_hdr *pls_layout; 45 struct pnfs_layout_hdr *pls_layout;
46 struct rpc_cred *pls_lc_cred; /* LAYOUTCOMMIT credential */
47 loff_t pls_end_pos; /* LAYOUTCOMMIT write end */
46}; 48};
47 49
48enum pnfs_try_status { 50enum pnfs_try_status {
@@ -152,7 +154,8 @@ bool pnfs_roc(struct inode *ino);
152void pnfs_roc_release(struct inode *ino); 154void pnfs_roc_release(struct inode *ino);
153void pnfs_roc_set_barrier(struct inode *ino, u32 barrier); 155void pnfs_roc_set_barrier(struct inode *ino, u32 barrier);
154bool pnfs_roc_drain(struct inode *ino, u32 *barrier); 156bool pnfs_roc_drain(struct inode *ino, u32 *barrier);
155 157void pnfs_set_layoutcommit(struct nfs_write_data *wdata);
158int pnfs_layoutcommit_inode(struct inode *inode, int sync);
156 159
157static inline int lo_fail_bit(u32 iomode) 160static inline int lo_fail_bit(u32 iomode)
158{ 161{
@@ -325,6 +328,10 @@ static inline void pnfs_clear_request_commit(struct nfs_page *req)
325{ 328{
326} 329}
327 330
331static inline int pnfs_layoutcommit_inode(struct inode *inode, int sync)
332{
333 return 0;
334}
328#endif /* CONFIG_NFS_V4_1 */ 335#endif /* CONFIG_NFS_V4_1 */
329 336
330#endif /* FS_NFS_PNFS_H */ 337#endif /* FS_NFS_PNFS_H */
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index e7aeda0663c5..a03c11f9081e 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1562,7 +1562,20 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr
1562 1562
1563int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) 1563int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
1564{ 1564{
1565 return nfs_commit_unstable_pages(inode, wbc); 1565 int ret;
1566
1567 ret = nfs_commit_unstable_pages(inode, wbc);
1568 if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) {
1569 int status, sync = wbc->sync_mode;
1570
1571 if (wbc->nonblocking || wbc->for_background)
1572 sync = 0;
1573
1574 status = pnfs_layoutcommit_inode(inode, sync);
1575 if (status < 0)
1576 return status;
1577 }
1578 return ret;
1566} 1579}
1567 1580
1568/* 1581/*